/*******************************************************************************
* Copyright (c) 2015 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.boot.dash.cloudfoundry.packaging;
import java.io.File;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
/**
* Responsible for picking the names for dependency jars when packaging a boot app.
* <p>
* This class could be turned into an interface with multiple implementations
* should we want to support different naming strategies. But for now there's
* just one implementation, so this is a concrete class.
*
* @author Kris De Volder
*/
public class JarNameGenerator {
private static final String UNKNOWN_DEPENDENCY = "unknown-dependency";
private static final IResource[] NO_RESOURCES = {};
private Set<String> used = new HashSet<String>();
private final String EXTENSION = ".jar";
public String createName(File dep) {
String candidate = getNameCandidate(dep);
return makeUnique(candidate);
}
private String makeUnique(String candidate) {
if (candidate.toLowerCase().endsWith(EXTENSION)) {
candidate = candidate.substring(0, candidate.length()-EXTENSION.length());
}
String name = candidate + EXTENSION;
int id = 0;
while (used.contains(name)) {
name = candidate+"-"+(++id) + EXTENSION;
}
used.add(name);
return name;
}
protected String getNameCandidate(File dep) {
if (isJar(dep)) {
return getNameCandidateForJar(dep);
} else if (dep.isDirectory()) {
return getNameCandidateForDir(dep);
}
//Shouldn't happen, but return something anyway
return UNKNOWN_DEPENDENCY;
}
private String getNameCandidateForDir(File dep) {
//We'll try to use the name of enclosing workspace project if possible
IProject p = getEnclosingProject(dep);
if (p!=null) {
return p.getName();
}
return UNKNOWN_DEPENDENCY;
}
protected IProject getEnclosingProject(File dep) {
IResource best = chooseBest(getResources(dep));
if (best!=null) {
return best.getProject();
}
return null;
}
/**
* If more than one resource matched a dependency we try to find the
* 'best' resource. We do this by looking at the path relative to the workspace
* and pick the one with the shortest path. This way we will pick the resource
* in the most nested project (i.e. when projects are nested a resource
* may exists both in the parent and child projects. We are interested in
* the child in this case.
*/
protected IResource chooseBest(IResource[] resources) {
int bestLen = Integer.MAX_VALUE;
IResource best = null;
for (IResource r : resources) {
int len = r.getFullPath().segmentCount();
if (len < bestLen) {
best = r;
bestLen = len;
}
}
return best;
}
protected IResource[] getResources(File dep) {
if (dep.isDirectory()) {
return getWorkspaceRoot().findContainersForLocationURI(dep.toURI());
} else if (dep.isFile()) {
return getWorkspaceRoot().findFilesForLocationURI(dep.toURI());
}
return NO_RESOURCES;
}
protected IWorkspaceRoot getWorkspaceRoot() {
return ResourcesPlugin.getWorkspace().getRoot();
}
protected String getNameCandidateForJar(File dep) {
return dep.getName();
}
protected boolean isJar(File dep) {
String name = dep.getName();
return name.endsWith(".jar") || name.endsWith(".JAR");
}
}