001/** 002 * Copyright 2010-2014 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 */ 016package org.kuali.common.util.metainf.service; 017 018import java.io.File; 019import java.io.IOException; 020import java.util.ArrayList; 021import java.util.Collections; 022import java.util.List; 023 024import org.apache.commons.io.FileUtils; 025import org.apache.commons.lang3.ArrayUtils; 026import org.apache.commons.lang3.StringUtils; 027import org.kuali.common.util.Str; 028import org.kuali.common.util.metainf.model.PathComparator; 029import org.kuali.common.util.metainf.spring.MetaInfDataLocation; 030import org.kuali.common.util.metainf.spring.MetaInfDataType; 031import org.kuali.common.util.metainf.spring.MetaInfGroup; 032import org.kuali.common.util.project.KualiUtilProjectConstants; 033import org.kuali.common.util.project.ProjectUtils; 034import org.kuali.common.util.project.model.Build; 035import org.kuali.common.util.project.model.Project; 036import org.kuali.common.util.project.model.ProjectIdentifier; 037import org.springframework.core.io.ClassPathResource; 038import org.springframework.core.io.Resource; 039import org.springframework.core.io.support.PathMatchingResourcePatternResolver; 040import org.springframework.util.ResourceUtils; 041 042import com.google.common.base.Optional; 043import com.google.common.collect.Lists; 044 045public class MetaInfUtils { 046 047 public static final String RESOURCES_FILENAME_EXTENSION = "resources"; 048 public static final String METAINF_DIRECTORY_NAME = "META-INF"; 049 050 /** 051 * @deprecated 052 */ 053 @Deprecated 054 public static final org.kuali.common.util.project.model.FeatureIdentifier FEATURE_ID = new org.kuali.common.util.project.model.FeatureIdentifier( 055 KualiUtilProjectConstants.PROJECT_ID, "metainf"); 056 057 public static final String PROPERTY_PREFIX = "metainf"; 058 059 /** 060 * <code>${project.build.outputDirectory}/META-INF/org/kuali/util/kuali-util/[group].resources</code> 061 */ 062 public static File getOutputFile(Project project, Build build, MetaInfGroup group) { 063 return getOutputFile(project, build, group.name().toLowerCase()); 064 } 065 066 /** 067 * <code>${project.build.outputDirectory}/META-INF/org/kuali/util/kuali-util/[filename].resources</code> 068 */ 069 public static File getOutputFile(Project project, Build build, String filename) { 070 return getOutputFile(project, build, Optional.<String> absent(), filename); 071 } 072 073 /** 074 * <code>${project.build.outputDirectory}/META-INF/org/kuali/util/kuali-util/[qualifier]/[group].resources</code> 075 */ 076 public static File getOutputFile(Project project, Build build, String qualifier, MetaInfGroup group) { 077 return getOutputFile(project, build, Optional.of(qualifier), group.name().toLowerCase()); 078 } 079 080 /** 081 * <code>${project.build.outputDirectory}/META-INF/org/kuali/util/kuali-util/[qualifier]/[filename].resources</code> 082 */ 083 public static File getOutputFile(Project project, Build build, String qualifier, String filename) { 084 return getOutputFile(project, build, Optional.of(qualifier), filename); 085 } 086 087 /** 088 * <code>${project.build.outputDirectory}/META-INF/org/kuali/util/kuali-util/[qualifier]/[filename].resources</code> where <code>[qualifier]</code> is optional 089 */ 090 public static File getOutputFile(Project project, Build build, Optional<String> qualifier, String filename) { 091 return getOutputFile(project, build, qualifier, Optional.<MetaInfDataLocation> absent(), Optional.<MetaInfDataType> absent(), filename); 092 } 093 094 /** 095 * <code>${project.build.outputDirectory}/META-INF/org/kuali/util/kuali-util/[qualifier]/[location]/[type]/[filename].resources</code> where <code>[qualifier]</code>, 096 * <code>[location]</code>, and <type>[type]</type> are optional 097 */ 098 public static File getOutputFile(Project project, Build build, Optional<String> qualifier, Optional<MetaInfDataLocation> location, Optional<MetaInfDataType> type, 099 String filename) { 100 StringBuilder sb = new StringBuilder(); 101 sb.append(getResourcePrefix(project)); 102 if (qualifier.isPresent()) { 103 sb.append("/"); 104 sb.append(qualifier.get()); 105 } 106 if (location.isPresent()) { 107 sb.append("/"); 108 sb.append(location.get().name().toLowerCase()); 109 } 110 if (type.isPresent()) { 111 sb.append("/"); 112 sb.append(type.get().name().toLowerCase()); 113 } 114 sb.append("/"); 115 sb.append(getFilename(filename)); 116 return new File(build.getOutputDir(), sb.toString()); 117 } 118 119 /** 120 * <code>classpath:META-INF/org/kuali/util/kuali-util/[group].resources</code> 121 */ 122 public static String getClasspathResource(ProjectIdentifier project, MetaInfGroup group) { 123 return getClasspathResource(project.getGroupId(), project.getArtifactId(), group); 124 } 125 126 /** 127 * <code>classpath:META-INF/org/kuali/util/kuali-util/[filename].resources</code> 128 */ 129 public static String getClasspathResource(ProjectIdentifier project, String filename) { 130 return getClasspathResource(project.getGroupId(), project.getArtifactId(), filename); 131 } 132 133 /** 134 * <code>classpath:META-INF/org/kuali/util/kuali-util/[qualifier]/[group].resources</code> 135 */ 136 public static String getClasspathResource(ProjectIdentifier project, String qualifier, MetaInfGroup group) { 137 return getClasspathResource(project.getGroupId(), project.getArtifactId(), Optional.of(qualifier), group.name().toLowerCase()); 138 } 139 140 /** 141 * <code>classpath:META-INF/org/kuali/util/kuali-util/[qualifier]/[filename].resources</code> 142 */ 143 public static String getClasspathResource(ProjectIdentifier project, String qualifier, String filename) { 144 return getClasspathResource(project.getGroupId(), project.getArtifactId(), Optional.of(qualifier), filename); 145 } 146 147 /** 148 * <code>classpath:META-INF/org/kuali/util/kuali-util/[qualifier]/[filename].resources</code> where <code>[qualifier]</code>, <code>[location]</code>, and <type>[type]</type> 149 * are optional 150 */ 151 public static String getClasspathResource(ProjectIdentifier project, Optional<String> qualifier, Optional<MetaInfDataLocation> location, Optional<MetaInfDataType> type, 152 String filename) { 153 return getClasspathResource(project.getGroupId(), project.getArtifactId(), qualifier, location, type, filename); 154 } 155 156 /** 157 * <code>classpath:META-INF/org/kuali/util/kuali-util/[group].resources</code> 158 */ 159 public static String getClasspathResource(Project project, MetaInfGroup group) { 160 return getClasspathResource(project.getGroupId(), project.getArtifactId(), group); 161 } 162 163 /** 164 * <code>classpath:META-INF/org/kuali/util/kuali-util/[filename].resources</code> 165 */ 166 public static String getClasspathResource(Project project, String filename) { 167 return getClasspathResource(project.getGroupId(), project.getArtifactId(), filename); 168 } 169 170 /** 171 * <code>classpath:META-INF/org/kuali/util/kuali-util/[qualifier]/[group].resources</code> 172 */ 173 public static String getClasspathResource(Project project, String qualifier, MetaInfGroup group) { 174 return getClasspathResource(project.getGroupId(), project.getArtifactId(), Optional.of(qualifier), group.name().toLowerCase()); 175 } 176 177 /** 178 * <code>classpath:META-INF/org/kuali/util/kuali-util/[qualifier]/[filename].resources</code> 179 */ 180 public static String getClasspathResource(Project project, String qualifier, String filename) { 181 return getClasspathResource(project.getGroupId(), project.getArtifactId(), Optional.of(qualifier), filename); 182 } 183 184 /** 185 * <code>classpath:META-INF/org/kuali/util/kuali-util/[qualifier]/[filename].resources</code> where <code>[qualifier]</code>, <code>[location]</code>, and <type>[type]</type> 186 * are optional 187 */ 188 public static String getClasspathResource(Project project, Optional<String> qualifier, Optional<MetaInfDataLocation> location, Optional<MetaInfDataType> type, String filename) { 189 return getClasspathResource(project.getGroupId(), project.getArtifactId(), qualifier, location, type, filename); 190 } 191 192 /** 193 * <code>classpath:META-INF/org/kuali/util/kuali-util/[group].resources</code> 194 */ 195 public static String getClasspathResource(String groupId, String artifactId, MetaInfGroup group) { 196 return getClasspathResource(groupId, artifactId, Optional.<String> absent(), group.name().toLowerCase()); 197 } 198 199 /** 200 * <code>classpath:META-INF/org/kuali/util/kuali-util/[filename].resources</code> 201 */ 202 public static String getClasspathResource(String groupId, String artifactId, String filename) { 203 return getClasspathResource(groupId, artifactId, Optional.<String> absent(), filename); 204 } 205 206 /** 207 * <code>classpath:META-INF/org/kuali/util/kuali-util/[qualifier]/[filename].resources</code> where <code>[qualifier]</code> is optional 208 */ 209 public static String getClasspathResource(String groupId, String artifactId, Optional<String> qualifier, String filename) { 210 return getClasspathResource(groupId, artifactId, qualifier, Optional.<MetaInfDataLocation> absent(), Optional.<MetaInfDataType> absent(), filename); 211 } 212 213 /** 214 * <code>classpath:META-INF/org/kuali/util/kuali-util/[qualifier]/[filename].resources</code> where <code>[qualifier]</code>, <code>[location]</code>, and <type>[type]</type> 215 * are optional 216 */ 217 public static String getClasspathResource(String groupId, String artifactId, Optional<String> qualifier, Optional<MetaInfDataLocation> location, 218 Optional<MetaInfDataType> type, String filename) { 219 StringBuilder sb = new StringBuilder(); 220 sb.append(ResourceUtils.CLASSPATH_URL_PREFIX); 221 sb.append(getResourcePrefix(groupId, artifactId)); 222 if (qualifier.isPresent()) { 223 sb.append("/"); 224 sb.append(qualifier.get()); 225 } 226 if (location.isPresent()) { 227 sb.append("/"); 228 sb.append(location.get().name().toLowerCase()); 229 } 230 if (type.isPresent()) { 231 sb.append("/"); 232 sb.append(type.get().name().toLowerCase()); 233 } 234 sb.append("/"); 235 sb.append(getFilename(filename)); 236 return sb.toString(); 237 } 238 239 /** 240 * List of <code>classpath:META-INF/org/kuali/util/kuali-util/[filename].resources</code> where <code>[filename]</code> can contain an Ant-style pattern 241 */ 242 public static List<String> getPatternedClasspathResources(ProjectIdentifier project, String filename) { 243 return getPatternedClasspathResources(project.getGroupId(), project.getArtifactId(), filename); 244 } 245 246 /** 247 * List of <code>classpath:META-INF/org/kuali/util/kuali-util/[qualifier]/[group].resources</code> where <code>[qualifier]</code> can contain an Ant-style pattern 248 */ 249 public static List<String> getPatternedClasspathResources(ProjectIdentifier project, String qualifier, MetaInfGroup group) { 250 return getPatternedClasspathResources(project.getGroupId(), project.getArtifactId(), Optional.of(qualifier), group.name().toLowerCase()); 251 } 252 253 /** 254 * List of <code>classpath:META-INF/org/kuali/util/kuali-util/[qualifier]/[filename].resources</code> where <code>[qualifier]</code> and <code>[filename]</code> can contain an 255 * Ant-style pattern 256 */ 257 public static List<String> getPatternedClasspathResources(ProjectIdentifier project, String qualifier, String filename) { 258 return getPatternedClasspathResources(project.getGroupId(), project.getArtifactId(), Optional.of(qualifier), filename); 259 } 260 261 /** 262 * List of <code>classpath:META-INF/org/kuali/util/kuali-util/[qualifier]/[location]/[type]/[filename].resources</code> where <code>[qualifier]</code>, <code>[location]</code>, 263 * and <type>[type]</type> are optional and <code>[qualifier]</code> and <code>[filename]</code> can contain an Ant-style pattern 264 */ 265 public static List<String> getPatternedClasspathResources(ProjectIdentifier project, Optional<String> qualifier, Optional<MetaInfDataLocation> location, 266 Optional<MetaInfDataType> type, String filename) { 267 return getPatternedClasspathResources(project.getGroupId(), project.getArtifactId(), qualifier, location, type, filename); 268 } 269 270 /** 271 * List of <code>classpath:META-INF/org/kuali/util/kuali-util/[filename].resources</code> where <code>[filename]</code> can contain an Ant-style pattern 272 */ 273 public static List<String> getPatternedClasspathResources(Project project, String filename) { 274 return getPatternedClasspathResources(project.getGroupId(), project.getArtifactId(), filename); 275 } 276 277 /** 278 * List of <code>classpath:META-INF/org/kuali/util/kuali-util/[qualifier]/[group].resources</code> where <code>[qualifier]</code> can contain an Ant-style pattern 279 */ 280 public static List<String> getPatternedClasspathResources(Project project, String qualifier, MetaInfGroup group) { 281 return getPatternedClasspathResources(project.getGroupId(), project.getArtifactId(), Optional.of(qualifier), group.name().toLowerCase()); 282 } 283 284 /** 285 * List of <code>classpath:META-INF/org/kuali/util/kuali-util/[qualifier]/[filename].resources</code> where <code>[qualifier]</code> and <code>[filename]</code> can contain an 286 * Ant-style pattern 287 */ 288 public static List<String> getPatternedClasspathResources(Project project, String qualifier, String filename) { 289 return getPatternedClasspathResources(project.getGroupId(), project.getArtifactId(), Optional.of(qualifier), filename); 290 } 291 292 /** 293 * List of <code>classpath:META-INF/org/kuali/util/kuali-util/[qualifier]/[location]/[type]/[filename].resources</code> where <code>[qualifier]</code>, <code>[location]</code>, 294 * and <type>[type]</type> are optional and <code>[qualifier]</code> and <code>[filename]</code> can contain an Ant-style pattern 295 */ 296 public static List<String> getPatternedClasspathResources(Project project, Optional<String> qualifier, Optional<MetaInfDataLocation> location, Optional<MetaInfDataType> type, 297 String filename) { 298 return getPatternedClasspathResources(project.getGroupId(), project.getArtifactId(), qualifier, location, type, filename); 299 } 300 301 /** 302 * List of <code>classpath:META-INF/org/kuali/util/kuali-util/[filename].resources</code> where <code>[filename]</code> can contain an Ant-style pattern 303 */ 304 public static List<String> getPatternedClasspathResources(String groupId, String artifactId, String filename) { 305 return getPatternedClasspathResources(groupId, artifactId, Optional.<String> absent(), filename); 306 } 307 308 /** 309 * List of <code>classpath:META-INF/org/kuali/util/kuali-util/[qualifier]/[filename].resources</code> where <code>[qualifier]</code> is optional * and <code>[qualifier]</code> 310 * and <code>[filename]</code> can contain an Ant-style pattern 311 */ 312 public static List<String> getPatternedClasspathResources(String groupId, String artifactId, Optional<String> qualifier, String filename) { 313 return getPatternedClasspathResources(groupId, artifactId, qualifier, Optional.<MetaInfDataLocation> absent(), Optional.<MetaInfDataType> absent(), filename); 314 } 315 316 /** 317 * List of <code>classpath:META-INF/org/kuali/util/kuali-util/[qualifier]/[filename].resources</code> where <code>[qualifier]</code>, <code>[location]</code>, and 318 * <type>[type]</type> are optional and <code>[qualifier]</code> and <code>[filename]</code> can contain an Ant-style pattern 319 */ 320 public static List<String> getPatternedClasspathResources(String groupId, String artifactId, Optional<String> qualifier, Optional<MetaInfDataLocation> location, 321 Optional<MetaInfDataType> type, String filename) { 322 List<String> patterenedClasspathResources = new ArrayList<String>(); 323 String classpathResource = getClasspathResource(groupId, artifactId, qualifier, location, type, filename); 324 PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); 325 try { 326 Resource[] resources = resolver.getResources(classpathResource); 327 if (ArrayUtils.isNotEmpty(resources)) { 328 for (Resource resource : resources) { 329 if (resource instanceof ClassPathResource) { 330 ClassPathResource classPathResource = (ClassPathResource) resource; 331 patterenedClasspathResources.add(ResourceUtils.CLASSPATH_URL_PREFIX + classPathResource.getPath()); 332 } 333 } 334 } 335 } catch (IOException ioe) { 336 throw new IllegalStateException("Unexpected IO error", ioe); 337 } 338 return patterenedClasspathResources; 339 } 340 341 /** 342 * Returns <code>[group].resources</code> (always lowercase) 343 */ 344 public static String getFilename(MetaInfGroup group) { 345 return getFilename(group.name().toLowerCase()); 346 } 347 348 /** 349 * Returns <code>[filename].resources</code> 350 */ 351 public static String getFilename(String filename) { 352 return filename + "." + RESOURCES_FILENAME_EXTENSION; 353 } 354 355 /** 356 * <code>META-INF/org/kuali/util</code> 357 */ 358 public static String getGroupPrefix(Project project) { 359 return getGroupPrefix(project.getGroupId()); 360 } 361 362 /** 363 * <code>META-INF/org/kuali/util</code> 364 */ 365 public static String getGroupPrefix(String groupId) { 366 return METAINF_DIRECTORY_NAME + "/" + Str.getPath(groupId); 367 } 368 369 /** 370 * <code>classpath:META-INF</code> 371 */ 372 public static String getClasspathPrefix() { 373 return ResourceUtils.CLASSPATH_URL_PREFIX + METAINF_DIRECTORY_NAME; 374 } 375 376 /** 377 * <code>META-INF/org/kuali/util/kuali-util</code> 378 */ 379 public static String getResourcePrefix(Project project) { 380 return getResourcePrefix(project.getGroupId(), project.getArtifactId()); 381 } 382 383 /** 384 * <code>META-INF/org/kuali/util/kuali-util</code> 385 */ 386 public static String getResourcePrefix(String groupId, String artifactId) { 387 return getGroupPrefix(groupId) + "/" + artifactId; 388 } 389 390 /** 391 * <code>META-INF/org/kuali/util/kuali-util</code> 392 */ 393 public static String getResourcePrefix(ProjectIdentifier project) { 394 return getResourcePrefix(project.getGroupId(), project.getArtifactId()); 395 } 396 397 /** 398 * <code>classpath:META-INF/org/kuali/util/kuali-util</code> 399 */ 400 public static String getClasspathResourcePrefix(ProjectIdentifier project) { 401 StringBuilder sb = new StringBuilder(); 402 sb.append(ResourceUtils.CLASSPATH_URL_PREFIX); 403 sb.append(getResourcePrefix(project.getGroupId(), project.getArtifactId())); 404 return sb.toString(); 405 } 406 407 /** 408 * <code>classpath:META-INF/org/kuali/util/kuali-util</code> 409 */ 410 public static String getClasspathResourcePrefix(Project project) { 411 StringBuilder sb = new StringBuilder(); 412 sb.append(ResourceUtils.CLASSPATH_URL_PREFIX); 413 sb.append(getResourcePrefix(project.getGroupId(), project.getArtifactId())); 414 return sb.toString(); 415 } 416 417 public static List<String> getQualifiers(File baseDirectory, ProjectIdentifier project, List<String> includes, List<String> excludes) { 418 String resourcePath = ProjectUtils.getResourcePath(project.getGroupId(), project.getArtifactId()); 419 File resourceDirectory = FileUtils.getFile(baseDirectory, resourcePath); 420 return getQualifiers(resourceDirectory, includes, excludes); 421 } 422 423 public static List<String> getQualifiers(File baseDirectory, Project project, List<String> includes, List<String> excludes) { 424 String resourcePath = ProjectUtils.getResourcePath(project.getGroupId(), project.getArtifactId()); 425 File resourceDirectory = FileUtils.getFile(baseDirectory, resourcePath); 426 return getQualifiers(resourceDirectory, includes, excludes); 427 } 428 429 /** 430 * @deprecated 431 */ 432 @Deprecated 433 public static List<String> getQualifiers(File baseDirectory, List<String> includes, List<String> excludes) { 434 List<String> qualifiers = Lists.newArrayList(); 435 org.kuali.common.util.SimpleScanner scanner = new org.kuali.common.util.SimpleScanner(baseDirectory, includes, excludes); 436 List<String> directories = scanner.getDirectories(); 437 Collections.sort(directories, new PathComparator()); 438 for (String directory : directories) { 439 if (qualifiers.isEmpty()) { 440 qualifiers.add(directory); 441 } else { 442 boolean matches = false; 443 for (String qualifier : qualifiers) { 444 matches |= StringUtils.startsWith(directory, qualifier); 445 } 446 if (!matches) { 447 qualifiers.add(directory); 448 } 449 } 450 } 451 return qualifiers; 452 } 453 454}