View Javadoc
1   /**
2    * Copyright 2010-2013 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.common.util;
17  
18  import java.io.File;
19  import java.util.ArrayList;
20  import java.util.Arrays;
21  import java.util.HashMap;
22  import java.util.List;
23  import java.util.Map;
24  import java.util.Properties;
25  import java.util.Set;
26  
27  import org.apache.commons.lang3.StringUtils;
28  import org.kuali.common.util.property.Constants;
29  import org.kuali.common.util.property.PropertiesContext;
30  import org.slf4j.Logger;
31  import org.slf4j.LoggerFactory;
32  import org.springframework.util.PropertyPlaceholderHelper;
33  
34  /**
35   * 
36   */
37  @Deprecated
38  public class ProjectUtils {
39  
40  	private static final Logger logger = LoggerFactory.getLogger(ProjectUtils.class);
41  	private static final PropertyPlaceholderHelper PPH = Constants.DEFAULT_PROPERTY_PLACEHOLDER_HELPER;
42  	private static final String CLASSPATH = "classpath:";
43  
44  	@Deprecated
45  	public static final String KUALI_COMMON_GROUP_ID = KualiProjectConstants.COMMON_GROUP_ID;
46  
47  	@Deprecated
48  	public static final String KUALI_UTIL_ARTIFACT_ID = UtilProjectContext.ARTIFACT_ID;
49  
50  	private static final Map<String, Properties> PROJECT_PROPERTIES_CACHE = new HashMap<String, Properties>();
51  
52  	public static List<Project> loadProjects(List<String> projectIds) {
53  		List<Project> projects = new ArrayList<Project>();
54  		for (String projectId : projectIds) {
55  			Project project = ProjectUtils.loadProject(projectId);
56  			projects.add(project);
57  		}
58  		return projects;
59  	}
60  
61  	/**
62  	 * <pre>
63  	 *   kuali-util = classpath:org/kuali/common/kuali-util
64  	 * </pre>
65  	 */
66  	public static String getCommonClassPathPrefix(String artifactId) {
67  		return getClassPathPrefix(KualiProjectConstants.COMMON_GROUP_ID, artifactId);
68  	}
69  
70  	/**
71  	 * Given a groupId and artifactId, convert the groupId to groupId.base, then return the classpath prefix
72  	 * 
73  	 * <pre>
74  	 *   org.kuali.student.db:ks-impex-rice-db = classpath:org/kuali/student/ks-impex-rice-db
75  	 *   org.kuali.common:kuali-util           = classpath:org/kuali/common/kuali-util
76  	 * </pre>
77  	 */
78  	public static String getClassPathPrefix(String groupId, String artifactId) {
79  		Project project = loadProject(groupId, artifactId);
80  		return CLASSPATH + getResourcePath(project);
81  	}
82  
83  	/**
84  	 * Given groupId:artifactId, convert the groupId to groupId.base, then return the classpath prefix
85  	 * 
86  	 * <pre>
87  	 *   org.kuali.student.db:ks-impex-rice-db = classpath:org/kuali/student/ks-impex-rice-db
88  	 *   org.kuali.common:kuali-util           = classpath:org/kuali/common/kuali-util
89  	 * </pre>
90  	 * 
91  	 * Use getClassPathPrefixFromProjectId() instead
92  	 */
93  	@Deprecated
94  	public static String getClassPathPrefixFromGAV(String projectId) {
95  		Project project = getProject(projectId);
96  		return getClassPathPrefix(project);
97  	}
98  
99  	/**
100 	 * Given groupId:artifactId, convert the groupId to groupId.base, then return the classpath prefix
101 	 * 
102 	 * <pre>
103 	 *   org.kuali.student.db:ks-impex-rice-db = classpath:org/kuali/student/ks-impex-rice-db
104 	 *   org.kuali.common:kuali-util           = classpath:org/kuali/common/kuali-util
105 	 * </pre>
106 	 */
107 	public static String getClassPathPrefixFromProjectId(String projectId) {
108 		Project project = getProject(projectId);
109 		return getClassPathPrefix(project);
110 	}
111 
112 	/**
113 	 * Given a project containing groupId + artifactId, convert the groupId to groupId.base, then return the classpath prefix
114 	 * 
115 	 * <pre>
116 	 *   org.kuali.student.db:ks-impex-rice-db = classpath:org/kuali/student/ks-impex-rice-db
117 	 *   org.kuali.common:kuali-util           = classpath:org/kuali/common/kuali-util
118 	 * </pre>
119 	 */
120 	public static String getClassPathPrefix(Project project) {
121 		return getClassPathPrefix(project.getGroupId(), project.getArtifactId());
122 	}
123 
124 	/**
125 	 * Given a groupId and artifactId, convert the groupId to groupId.base, then return a resource path relative to directory
126 	 * 
127 	 * <pre>
128 	 *   org.kuali.student.db:ks-impex-rice-db    = org/kuali/student/ks-impex-rice-db
129 	 *   org.kuali.common:kuali-util              = org/kuali/common/kuali-util
130 	 *   
131 	 *   /tmp/x/y/z + org.kuali.common:kuali-util = /tmp/x/y/z/org/kuali/common/kuali-util
132 	 * </pre>
133 	 */
134 	public static File getResourceDirectory(File directory, Project project) {
135 		String resourcePath = getResourcePath(project);
136 		File file = new File(directory, resourcePath);
137 		return new File(LocationUtils.getCanonicalPath(file));
138 	}
139 
140 	/**
141 	 * Given a groupId and artifactId, convert the groupId to groupId.base, then return a handle to a file relative to directory with the given filename
142 	 * 
143 	 * <pre>
144 	 *   org.kuali.student.db:ks-impex-rice-db              = org/kuali/student/ks-impex-rice-db
145 	 *   org.kuali.common:kuali-util                        = org/kuali/common/kuali-util
146 	 *   
147 	 *   /tmp/x/y/z + org.kuali.common:kuali-util + foo.txt = /tmp/x/y/z/org/kuali/common/kuali-util/foo.txt
148 	 * </pre>
149 	 */
150 	public static File getResourceFile(File directory, Project project, String filename) {
151 		File dir = getResourceDirectory(directory, project);
152 		return new File(dir, filename);
153 	}
154 
155 	/**
156 	 * Given groupId:artifactId, convert the groupId to groupId.base, then return a resource friendly prefix
157 	 * 
158 	 * <pre>
159 	 *   org.kuali.student.db:ks-impex-rice-db = org/kuali/student/ks-impex-rice-db
160 	 *   org.kuali.common:kuali-util           = org/kuali/common/kuali-util
161 	 * </pre>
162 	 */
163 	public static String getResourcePath(Project project) {
164 		Properties properties = project.getProperties();
165 		String groupIdPath = properties.getProperty(Constants.GROUP_ID_PATH_KEY);
166 		Assert.hasText(groupIdPath, "groupIdPath has no text");
167 		String artifactId = project.getArtifactId();
168 		return groupIdPath + "/" + artifactId;
169 	}
170 
171 	/**
172 	 * 
173 	 */
174 	@Deprecated
175 	public static org.kuali.common.util.property.ProjectProperties getProjectProperties(ProjectContext context) {
176 
177 		// Get a project object based on the context information
178 		Project project = loadProject(context);
179 
180 		// Create a properties context object from the project.properties file from META-INF
181 		PropertiesContext propertiesContext = new PropertiesContext(project.getProperties());
182 		propertiesContext.setEncoding(project.getEncoding());
183 		propertiesContext.setLocations(context.getPropertyLocations());
184 
185 		// Return a project properties object
186 		return new org.kuali.common.util.property.ProjectProperties(project, propertiesContext);
187 	}
188 
189 	/**
190 	 * Create a <code>Project</code> object from the <code>context</code>. This includes loading the corresponding <code>project.properties</code> file from disk.
191 	 */
192 	@Deprecated
193 	public static Project loadProject(ProjectContext context) {
194 		return loadProject(getGav(context));
195 	}
196 
197 	@Deprecated
198 	public static String getGav(ProjectContext context) {
199 		return getGav(context.getGroupId(), context.getArtifactId());
200 	}
201 
202 	@Deprecated
203 	public static String getGav(Project project) {
204 		return getGav(project.getGroupId(), project.getArtifactId());
205 	}
206 
207 	@Deprecated
208 	public static String getGav(String groupId, String artifactId) {
209 		return groupId + ":" + artifactId;
210 	}
211 
212 	public static String getProjectId(Project project) {
213 		return getProjectId(project.getGroupId(), project.getArtifactId());
214 	}
215 
216 	public static String getProjectId(String groupId, String artifactId) {
217 		return groupId + ":" + artifactId;
218 	}
219 
220 	/**
221 	 * Create a <code>Project</code> object from <code>groupId</code>, <code>artifactId</code> pair. This includes loading the corresponding <code>project.properties</code> file
222 	 * from disk.
223 	 */
224 	public static Project loadProject(String groupId, String artifactId) {
225 		String projectId = getProjectId(groupId, artifactId);
226 		return loadProject(projectId);
227 	}
228 
229 	/**
230 	 * Create a <code>Project</code> object from the <code>projectId</code>. This includes loading the corresponding <code>project.properties</code> file from disk.
231 	 */
232 	public static Project loadProject(String projectId) {
233 		// Convert the projectId into a Project
234 		Project project = getProject(projectId);
235 
236 		// Load properties from a .properties file for this project
237 		Properties properties = loadProperties(project);
238 
239 		// Return a fully configured project object based on the properties
240 		Project loadedProject = getProject(properties);
241 
242 		// return the project we loaded
243 		return loadedProject;
244 	}
245 
246 	/**
247 	 * Provide a way to clear the cache
248 	 */
249 	public synchronized static void clearCache() {
250 		PROJECT_PROPERTIES_CACHE.clear();
251 	}
252 
253 	/**
254 	 * Create a skeleton <code>Project</code> object from the <code>gav</code>. Nothing but the GAV info (groupId:artifactId:packaging:version:classifier) gets filled in. Does not
255 	 * read <code>project.properties</code> from disk.
256 	 */
257 	public static Project getProject(String gav) {
258 		logger.debug("Processing [{}]", gav);
259 		String[] tokens = StringUtils.split(gav, ":");
260 
261 		Project project = new Project();
262 		if (tokens.length > 0) {
263 			project.setGroupId(RepositoryUtils.toNull(tokens[0]));
264 		}
265 		if (tokens.length > 1) {
266 			project.setArtifactId(RepositoryUtils.toNull(tokens[1]));
267 		}
268 		if (tokens.length > 2) {
269 			project.setPackaging(RepositoryUtils.toNull(tokens[2]));
270 		}
271 		if (tokens.length > 3) {
272 			project.setVersion(RepositoryUtils.toNull(tokens[3]));
273 		}
274 		if (tokens.length > 4) {
275 			project.setClassifier(RepositoryUtils.toNull(tokens[4]));
276 		}
277 		return project;
278 	}
279 
280 	public static List<Dependency> getDependencies(String csv) {
281 		List<String> tokens = CollectionUtils.getTrimmedListFromCSV(csv);
282 		List<Dependency> dependencies = new ArrayList<Dependency>();
283 		for (String token : tokens) {
284 			Dependency dependency = RepositoryUtils.parseDependency(token);
285 			dependencies.add(dependency);
286 		}
287 		return dependencies;
288 	}
289 
290 	/**
291 	 * Return a <code>Project</code> object by copying values from the <code>properties</code> object into a <code>Project</code> object.
292 	 */
293 	public static Project getProject(Properties properties) {
294 		List<String> skipKeys = Arrays.asList("project.dependencies");
295 		String startsWith = "project.";
296 		List<String> keys = PropertyUtils.getStartsWithKeys(properties, startsWith);
297 		Project project = new Project();
298 		project.setProperties(properties);
299 		Map<String, Object> description = ReflectionUtils.describe(project);
300 		Set<String> beanProperties = description.keySet();
301 		for (String key : keys) {
302 			if (skipKeys.contains(key)) {
303 				continue;
304 			}
305 			String value = properties.getProperty(key);
306 			String beanProperty = getBeanProperty(key, startsWith);
307 			if (beanProperties.contains(beanProperty)) {
308 				ReflectionUtils.copyProperty(project, beanProperty, value);
309 			}
310 		}
311 		String csv = RepositoryUtils.toNull(properties.getProperty("project.dependencies"));
312 		List<Dependency> dependencies = getDependencies(csv);
313 		project.setDependencies(dependencies);
314 		return project;
315 	}
316 
317 	protected static String getBeanProperty(String key, String startsWith) {
318 		String s = StringUtils.substring(key, startsWith.length());
319 		String[] tokens = StringUtils.split(s, ".");
320 		StringBuilder sb = new StringBuilder();
321 		for (int i = 0; i < tokens.length; i++) {
322 			String token = tokens[i];
323 			if (i == 0) {
324 				sb.append(token);
325 			} else {
326 				sb.append(StringUtils.capitalize(token));
327 			}
328 		}
329 		return sb.toString();
330 	}
331 
332 	public static Properties loadProperties(String gav) {
333 		return loadProperties(getProject(gav));
334 	}
335 
336 	/**
337 	 * Use the groupId and artifactId from this project to load the corresponding project.properties file and cache it in our internal Map
338 	 */
339 	public static synchronized Properties loadProperties(Project project) {
340 		String projectId = getProjectId(project.getGroupId(), project.getArtifactId());
341 		Properties properties = PROJECT_PROPERTIES_CACHE.get(projectId);
342 		if (properties == null) {
343 			properties = loadAndCache(project, projectId);
344 		}
345 		return properties;
346 	}
347 
348 	protected static Properties loadAndCache(Project project, String projectId) {
349 		String location = getPropertiesFileLocation(project);
350 
351 		// If it doesn't exist, we've got issues
352 		Assert.exists(location);
353 
354 		Properties properties = PropertyUtils.load(location);
355 		PROJECT_PROPERTIES_CACHE.put(projectId, properties);
356 		return properties;
357 	}
358 
359 	public static String getPropertiesFileLocation(Project project) {
360 		Assert.hasText(project.getGroupId(), "groupId has no text");
361 		Assert.hasText(project.getArtifactId(), "artifactId has no text");
362 
363 		Properties properties = new Properties();
364 		properties.setProperty(Constants.GROUP_ID_PATH_KEY, Str.getPath(project.getGroupId()));
365 		properties.setProperty(Constants.ARTIFACT_ID_KEY, project.getArtifactId());
366 
367 		return PPH.replacePlaceholders(Constants.PROJECT_PROPERTIES_LOCATION, properties);
368 	}
369 
370 }