View Javadoc
1   package org.kuali.common.devops.logic;
2   
3   import static com.google.common.base.Optional.absent;
4   import static com.google.common.base.Optional.fromNullable;
5   import static com.google.common.collect.Lists.newArrayList;
6   
7   import java.util.List;
8   import java.util.Properties;
9   
10  import org.apache.commons.lang.StringUtils;
11  import org.kuali.common.util.LocationUtils;
12  import org.kuali.common.util.project.model.ImmutableProject;
13  import org.kuali.common.util.project.model.Project;
14  
15  import com.google.common.base.Joiner;
16  import com.google.common.base.Optional;
17  import com.google.common.base.Splitter;
18  
19  public class Projects extends Examiner {
20  
21  	private static final String BUNDLE_SYMBOLIC_NAME_KEY = "Bundle-SymbolicName";
22  
23  	public static Project getProjectWithAccurateSCMInfo(Project project, Properties manifest) {
24  		Optional<String> bundleSymbolicName = fromNullable(manifest.getProperty(BUNDLE_SYMBOLIC_NAME_KEY));
25  		if (!bundleSymbolicName.isPresent()) {
26  			return ImmutableProject.copyOf(project);
27  		} else {
28  			Properties newProps = new Properties();
29  			newProps.putAll(project.getProperties());
30  
31  			// Most reliable way to get SVN information is from the manifest. This method attempts to get it from both
32  			// MANIFEST.MF and project.properties. It also verifies that it can actually contact whatever location it locates
33  			// before returning it
34  			Optional<String> url = getScmUrl(manifest, newProps);
35  			String revision = getScmRevision(manifest);
36  
37  			if (url.isPresent()) {
38  				// Override whatever is in the project properties with what we found
39  				newProps.setProperty(SCM_URL_KEY, url.get());
40  				newProps.setProperty(SCM_REVISION_KEY, revision);
41  			} else {
42  				// Remove these 2 properties so nothing can even attempt to display inaccurate SCM info
43  				newProps.remove(SCM_URL_KEY);
44  				newProps.remove(SCM_REVISION_KEY);
45  			}
46  			return new ImmutableProject(project.getGroupId(), project.getArtifactId(), project.getVersion(), newProps);
47  		}
48  	}
49  
50  	/**
51  	 * Returns Optional.absent() unless we can locate a live URL that we can actually contact
52  	 */
53  	private static Optional<String> getScmUrl(Properties manifest, Properties properties) {
54  		// Most reliable method for getting the url is via MANIFEST.MF
55  		Optional<String> url = getScmUrlFromManifest(manifest);
56  		if (url.isPresent()) {
57  			// If we found one, we are done
58  			return url;
59  		} else {
60  			// If MANIFEST.MF fails, try to get it from project.properties
61  			// The problem here, is that Maven assumes artifactId == directory name for sub-modules
62  			// If that isn't the case, the URL from project.properties points to a non-existent location
63  			return getScmUrlFromProperties(properties);
64  		}
65  	}
66  
67  	private static Optional<String> getScmUrlFromManifest(Properties manifest) {
68  		String url = manifest.getProperty("SVN-URL");
69  		if (url == null) {
70  			return absent();
71  		}
72  		if (url.indexOf("${") != -1) {
73  			return absent();
74  		}
75  		if (!LocationUtils.exists(url)) {
76  			return absent();
77  		}
78  		return Optional.of(url);
79  	}
80  
81  	private static Optional<String> getScmUrlFromProperties(Properties properties) {
82  		String url = properties.getProperty("project.scm.url");
83  		if (url == null) {
84  			return Optional.absent();
85  		}
86  		List<String> tokens = newArrayList(Splitter.on(':').splitToList(url));
87  		tokens.remove(0); // scm
88  		tokens.remove(0); // svn
89  		String newUrl = Joiner.on(':').join(tokens);
90  
91  		// Make sure the location actually exists
92  		if (LocationUtils.exists(newUrl)) {
93  			return Optional.of(newUrl);
94  		} else {
95  			return absent();
96  		}
97  	}
98  
99  	private static String getScmRevision(Properties manifest) {
100 		String revision = StringUtils.trimToNull(manifest.getProperty("SVN-Revision"));
101 		if (revision == null || revision.indexOf("${") != -1) {
102 			return "n/a";
103 		} else {
104 			return revision;
105 		}
106 	}
107 
108 }