001 /** 002 * Copyright 2010-2013 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.common.util; 017 018 import java.io.File; 019 import java.util.ArrayList; 020 import java.util.List; 021 022 import org.apache.commons.io.FileUtils; 023 import org.apache.commons.lang3.StringUtils; 024 import org.kuali.common.util.nullify.NullUtils; 025 026 public class RepositoryUtils { 027 028 private static final String FS = File.separator; 029 private static final String DEFAULT_MAVEN_REPO_PATH = ".m2" + FS + "repository"; 030 private static final String GAV_DELIMITER = ":"; 031 032 public static final void copyArtifact(String repository, Artifact artifact) { 033 File file = getFile(artifact); 034 copyArtifactToFile(repository, artifact, file); 035 } 036 037 public static final void copyArtifactToDirectory(String repository, Artifact artifact, File directory) { 038 String filename = getFilename(artifact); 039 File file = new File(directory, filename); 040 copyArtifactToFile(repository, artifact, file); 041 } 042 043 public static final void copyArtifactToFile(String repository, Artifact artifact, File file) { 044 String location = repository + getRepositoryPath(artifact); 045 LocationUtils.copyLocationToFile(location, file); 046 } 047 048 /** 049 * <p> 050 * Order is <code>groupId:artifactId:version:classifier:type</code>. The ordering here matches the order Maven uses to create actual files. Which is different from what the 051 * toString() method on Maven's Artifact object produces. 052 * </p> 053 * 054 * <p> 055 * Trailing <code>:</code>'s are omitted. 056 * </p> 057 * 058 * <p> 059 * If every field is left blank, <code>::::</code> is returned. 060 * </p> 061 * 062 * <pre> 063 * org.kuali.common:kuali-jdbc:1.0.0:webapp:jar - groupId + artifactId + version + classifier + type 064 * org.kuali.common:kuali-jdbc:1.0.0::jar - no classifier 065 * :::: - Every field is blank 066 * org.kuali.common - groupId only 067 * ::::jar - type only 068 * :kuali-jdbc:::jar - no groupId, version, classifier, or type 069 * org.kuali.common:kuali-jdbc - groupId + artifactId 070 * org.kuali.common:kuali-jdbc:1.0.0 - groupId + artifactId + version 071 * org.kuali.common:kuali-jdbc:1.0.0:webapp - no type 072 * org.kuali.common:kuali-jdbc:1.0.0 - no classifier or type 073 * org.kuali.common:kuali-jdbc::webapp:jar - no version 074 * </pre> 075 */ 076 public static final String toString(Artifact artifact) { 077 List<String> tokens = new ArrayList<String>(); 078 tokens.add(toEmpty(artifact.getGroupId())); 079 tokens.add(toEmpty(artifact.getArtifactId())); 080 tokens.add(toEmpty(artifact.getVersion())); 081 tokens.add(toEmpty(artifact.getClassifier())); 082 tokens.add(toEmpty(artifact.getType())); 083 int delimiterCount = getDelimiterCount(tokens); 084 return getDelimitedString(tokens, delimiterCount, GAV_DELIMITER); 085 } 086 087 /** 088 * <p> 089 * Order is <code>groupId:artifactId:version:classifier:type:scope</code>. The ordering here matches the order Maven uses to create actual files. As opposed to what the 090 * toString() method on Maven's Dependency object produces. 091 * </p> 092 * 093 * <p> 094 * Trailing <code>:</code>'s are omitted. 095 * </p> 096 * 097 * <p> 098 * If every field is left blank, <code>:::::</code> is returned. 099 * </p> 100 * 101 * <pre> 102 * org.kuali.common:kuali-jdbc:1.0.0:webapp:jar:compile - groupId + artifactId + version + classifier + type + scope 103 * org.kuali.common:kuali-jdbc:1.0.0::jar:compile - no classifier 104 * org.kuali.common:kuali-jdbc:1.0.0:webapp:jar: - no scope 105 * ::::: - Every field is blank 106 * org.kuali.common - groupId only 107 * :::::compile - scope only 108 * :kuali-jdbc:::jar - artifactId + type 109 * org.kuali.common:kuali-jdbc - groupId + artifactId 110 * org.kuali.common:kuali-jdbc:1.0.0 - groupId + artifactId + version 111 * org.kuali.common:kuali-jdbc:1.0.0:webapp - groupId + artifactId + version + classifier 112 * org.kuali.common:kuali-jdbc:1.0.0:::compile - no classifier or type 113 * org.kuali.common:kuali-jdbc::webapp:jar:compile - no version 114 * </pre> 115 */ 116 public static final String toString(Dependency dependency) { 117 List<String> tokens = new ArrayList<String>(); 118 tokens.add(toEmpty(dependency.getGroupId())); 119 tokens.add(toEmpty(dependency.getArtifactId())); 120 tokens.add(toEmpty(dependency.getVersion())); 121 tokens.add(toEmpty(dependency.getClassifier())); 122 tokens.add(toEmpty(dependency.getType())); 123 tokens.add(toEmpty(dependency.getScope())); 124 int delimiterCount = getDelimiterCount(tokens); 125 return getDelimitedString(tokens, delimiterCount, GAV_DELIMITER); 126 } 127 128 /** 129 * <p> 130 * Order is <code>groupId:artifactId:version:classifier:type:scope</code>. 131 * </p> 132 */ 133 public static final Artifact parseArtifact(String gav) { 134 Assert.hasText(gav, "gav has no text"); 135 136 String[] tokens = StringUtils.splitPreserveAllTokens(gav, GAV_DELIMITER); 137 int len = tokens.length; 138 for (int i = 0; i < len; i++) { 139 tokens[i] = toNull(tokens[i]); 140 } 141 142 Artifact a = new Artifact(); 143 if (len > 0) { 144 a.setGroupId(tokens[0]); 145 } 146 if (len > 1) { 147 a.setArtifactId(tokens[1]); 148 } 149 if (len > 2) { 150 a.setVersion(tokens[2]); 151 } 152 if (len > 3) { 153 a.setClassifier(tokens[3]); 154 } 155 if (len > 4) { 156 a.setType(tokens[4]); 157 } 158 return a; 159 } 160 161 /** 162 * <p> 163 * Order is <code>groupId:artifactId:version:classifier:type:scope</code>. 164 * </p> 165 */ 166 public static final Dependency parseDependency(String gav) { 167 Assert.hasText(gav, "gav has no text"); 168 169 String[] tokens = StringUtils.splitPreserveAllTokens(gav, GAV_DELIMITER); 170 int len = tokens.length; 171 for (int i = 0; i < len; i++) { 172 tokens[i] = toNull(tokens[i]); 173 } 174 175 Dependency d = new Dependency(); 176 if (len > 0) { 177 d.setGroupId(tokens[0]); 178 } 179 if (len > 1) { 180 d.setArtifactId(tokens[1]); 181 } 182 if (len > 2) { 183 d.setVersion(tokens[2]); 184 } 185 if (len > 3) { 186 d.setClassifier(tokens[3]); 187 } 188 if (len > 4) { 189 d.setType(tokens[4]); 190 } 191 if (len > 5) { 192 d.setScope(tokens[5]); 193 } 194 return d; 195 } 196 197 protected static final String getDelimitedString(List<String> tokens, int delimiterCount, String delimiter) { 198 StringBuilder sb = new StringBuilder(); 199 for (int i = 0; i < tokens.size(); i++) { 200 if (i != 0 && i < delimiterCount) { 201 sb.append(delimiter); 202 } 203 sb.append(tokens.get(i)); 204 } 205 return sb.toString(); 206 } 207 208 protected static final int getDelimiterCount(List<String> tokens) { 209 int count = 0; 210 for (int i = 0; i < tokens.size(); i++) { 211 String token = toEmpty(tokens.get(i)); 212 if (!StringUtils.isEmpty(token)) { 213 count = i + 1; 214 } 215 } 216 return count == 0 ? tokens.size() : count; 217 } 218 219 /** 220 * Return null if token is blank, "NULL", or "NONE" 221 */ 222 public static String toNull(String token) { 223 if (StringUtils.isBlank(token)) { 224 return null; 225 } 226 if (NullUtils.isNullOrNone(token)) { 227 return null; 228 } 229 return token; 230 } 231 232 /** 233 * Return the empty string if token is blank, "NULL", or "NONE" 234 */ 235 public static String toEmpty(String token) { 236 if (StringUtils.isBlank(token)) { 237 return ""; 238 } 239 if (NullUtils.isNullOrNone(token)) { 240 return ""; 241 } 242 return token; 243 } 244 245 public static final String getRepositoryPath(Artifact artifact) { 246 StringBuilder sb = new StringBuilder(); 247 sb.append(Str.getPath(artifact.getGroupId())); 248 sb.append(FS); 249 sb.append(artifact.getArtifactId()); 250 sb.append(FS); 251 sb.append(artifact.getVersion()); 252 return sb.toString(); 253 } 254 255 /** 256 * Return true if classifier should become part of the filename 257 */ 258 protected static boolean addClassifierToFilename(String classifier) { 259 return !StringUtils.isBlank(classifier) && !NullUtils.isNullOrNone(classifier); 260 } 261 262 public static final String getFilename(Artifact artifact) { 263 StringBuilder sb = new StringBuilder(); 264 sb.append(artifact.getArtifactId()); 265 sb.append("-"); 266 sb.append(artifact.getVersion()); 267 if (addClassifierToFilename(artifact.getClassifier())) { 268 sb.append("-"); 269 sb.append(artifact.getClassifier()); 270 } 271 sb.append("."); 272 sb.append(artifact.getType()); 273 return sb.toString(); 274 } 275 276 public static final File getDefaultLocalRepositoryDir() { 277 return new File(FileUtils.getUserDirectoryPath() + FS + DEFAULT_MAVEN_REPO_PATH); 278 } 279 280 public static final File getFile(Artifact artifact) { 281 return getFile(getDefaultLocalRepositoryDir(), artifact); 282 } 283 284 public static final File getFile(File localRepositoryDir, Artifact artifact) { 285 String path = getRepositoryPath(artifact); 286 String filename = getFilename(artifact); 287 return new File(localRepositoryDir.getAbsolutePath() + FS + path, filename); 288 } 289 290 }