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 }