package org.dru.clay.rhino.feature.ivy;
import com.google.gson.reflect.TypeToken;
import org.dru.clay.resolver.DependencyResolver;
import org.dru.clay.resolver.DependencyResolverImpl;
import org.dru.clay.respository.Repository;
import org.dru.clay.respository.artifact.Group;
import org.dru.clay.respository.artifact.UnresolvedArtifact;
import org.dru.clay.respository.artifact.VersionPattern;
import org.dru.clay.respository.cache.CacheIvyRepository;
import org.dru.clay.respository.dependency.ConfigurationMapping;
import org.dru.clay.respository.dependency.Dependency;
import org.dru.clay.respository.ivy.ConfigurationMappingParser;
import org.dru.clay.respository.ivy.IvyRepository;
import org.dru.clay.respository.transport.Transport;
import org.dru.clay.respository.transport.filesystem.FileSystemOptions;
import org.dru.clay.respository.transport.filesystem.FileSystemTransport;
import org.dru.clay.respository.transport.http.HttpTransport;
import org.dru.clay.rhino.feature.Feature;
import org.dru.clay.rhino.util.RhinoUtils;
import org.dru.clay.util.file.FileFunctions;
import org.dru.clay.util.functional.CollectionUtils;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import java.io.File;
import java.net.URI;
import java.util.*;
public class Ivy extends Feature {
public static final String[] FUNCTION_NAMES = { "Ivy_configure", "Ivy_dependencies", "Ivy_resolve" };
private static final String CONFIG_KEY = "IvyConfiguration";
private static final String DEPENDENCY_KEY = "IvyDependencies";
@Override
public void init(Context context, ScriptableObject scope) throws Exception {
scope.defineFunctionProperties(FUNCTION_NAMES, Ivy.class, ScriptableObject.DONTENUM);
loadFeatureScript(context, scope, Ivy.class);
}
public static void Ivy_configure(final Context context, final Scriptable thisObj, final Object[] args, final Function funcObj)
throws Exception {
final IvyConfiguration configuration = RhinoUtils.decode(context, thisObj, args[0], IvyConfiguration.class);
((ScriptableObject) thisObj).associateValue(CONFIG_KEY, configuration);
}
public static void Ivy_dependencies(final Context context, final Scriptable thisObj, final Object[] args, final Function funcObj)
throws Exception {
final Map<String, Collection<IvyDependency>> ivyDependencies = RhinoUtils.decode(context, thisObj, args[0], new TypeToken<Map<String, Collection<IvyDependency>>>() {});
final ConfigurationMappingParser mappingParser = new ConfigurationMappingParser();
final Map<String, Collection<Dependency>> dependencyMap = new HashMap<String, Collection<Dependency>>();
for (Map.Entry<String, Collection<IvyDependency>> entry : ivyDependencies.entrySet()) {
final String configuration = entry.getKey();
final Collection<Dependency> dependencies = new ArrayList<Dependency>();
for (IvyDependency dependency : entry.getValue()) {
final ConfigurationMapping mapping = mappingParser.parse(dependency.getConf());
final UnresolvedArtifact artifact = new UnresolvedArtifact(dependency.getName(), new VersionPattern(dependency.getRev()));
dependencies.add(new Dependency(new Group(dependency.getOrg()), artifact, mapping, true));
}
dependencyMap.put(configuration, dependencies);
}
((ScriptableObject) thisObj).associateValue(DEPENDENCY_KEY, dependencyMap);
}
@SuppressWarnings("unchecked")
public static Object Ivy_resolve(final Context context, final Scriptable thisObj, final Object[] args, final Function funcObj)
throws Exception {
IvyConfiguration ivyConfig = (IvyConfiguration) ((ScriptableObject) thisObj).getAssociatedValue(CONFIG_KEY);
if (ivyConfig == null || ivyConfig.getLocation() == null) {
throw new IllegalStateException("Ivy repository is not properly configured. Missing required value 'location'.");
}
URI location = new URI(ivyConfig.getLocation());
Transport transport = getTransport(location.getScheme());
Repository repository = new IvyRepository(location, ivyConfig.getIvyPattern(), ivyConfig.getArtifactPattern());
CacheIvyRepository cacheIvyRepository = new CacheIvyRepository(new File(ivyConfig.getCacheDir()), repository, transport);
final DependencyResolver resolver = new DependencyResolverImpl(cacheIvyRepository, transport);
final Map<String, Collection<Dependency>> dependencyMap = (Map<String, Collection<Dependency>> )((ScriptableObject) thisObj).getAssociatedValue(DEPENDENCY_KEY);
resolver.begin();
Collection<File> resolvedFiles = new HashSet<File>();
for (String configuration : toStringArray(args)) {
final Collection<Dependency> dependencies = dependencyMap.get(configuration);
resolver.resolve(new File(ivyConfig.getResolveDir()), configuration, dependencies);
}
resolvedFiles.addAll(resolver.end());
return RhinoUtils.fromCollection(context, thisObj, CollectionUtils.transform(resolvedFiles, FileFunctions.path()));
}
private static Transport getTransport(String scheme) {
if ("file".equalsIgnoreCase(scheme)) {
return new FileSystemTransport(FileSystemOptions.CreateDirectories);
}
if ("http".equalsIgnoreCase(scheme)) {
return new HttpTransport();
}
throw new UnsupportedOperationException("Unsupported scheme '" + scheme + "'!");
}
}