package monolipse.core.runtime;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Collection;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import monolipse.core.IAssemblyReference;
import monolipse.core.IMonoLauncher;
import monolipse.core.IMonoRuntime;
import monolipse.core.IRemembrance;
import monolipse.core.foundation.IOUtilities;
import monolipse.core.internal.GlobalAssemblyCacheReference;
import org.eclipse.core.runtime.Platform;
public class MonoRuntimeImpl implements IMonoRuntime {
private static final Map<Object, IAssemblyReference> _cachedGacReferences = new TreeMap<Object, IAssemblyReference>();
private static boolean _gacInitialized = false;
static final Pattern ASSEMBLY_NAME_PATTERN = Pattern
.compile("\\s*([^,]+),\\s*Version=([^,]+),\\s*Culture=([^,]+),\\s*PublicKeyToken=([^,]+)($|,\\s*Custom=null)$");
public static final String PATH_GACUTIL = "lib/mono/4.0/gacutil.exe";
public static String getOSDependentRuntimeExecutable(String runtimeLocation)
throws IOException {
String path = IOUtilities.combinePath(runtimeLocation, MonoRuntimeImpl.RUNTIME_EXECUTABLE);
return Platform.OS_WIN32.equals(Platform.getOS())
? path + ".exe"
: path;
}
private static IAssemblyReference[] toArray(Collection<IAssemblyReference> references) {
return references
.toArray(new IAssemblyReference[references.size()]);
}
String _location;
public static final String RUNTIME_EXECUTABLE = "bin/mono";
public MonoRuntimeImpl(String location) {
if (null == location)
throw new IllegalArgumentException("location cannot be null");
_location = location;
}
private Object cacheKey(String name, String version, String culture,
String token) {
return name + version + culture + token;
}
private IAssemblyReference createAndCacheReference(String name,
String version, String culture, String token) {
IAssemblyReference reference = new GlobalAssemblyCacheReference(name,
version, culture, token);
_cachedGacReferences.put(cacheKey(name, version, culture, token),
reference);
return reference;
}
public IMonoLauncher createLauncher(String executablePath)
throws IOException {
MonoLauncherImpl launcher = new MonoLauncherImpl(MonoRuntimeImpl.getOSDependentRuntimeExecutable(_location));
launcher.add("--runtime=v4.0");
launcher.add("--debug");
launcher.add(executablePath);
return launcher;
}
private IAssemblyReference getCachedReference(String name, String version,
String culture, String token) {
return _cachedGacReferences.get(cacheKey(name,
version, culture, token));
}
public IAssemblyReference getGlobalAssemblyCacheReference(String name,
String version, String culture, String token) {
IAssemblyReference reference = getCachedReference(name, version,
culture, token);
if (null == reference) {
reference = createAndCacheReference(name, version, culture, token);
}
return reference;
}
public String getLocation() {
return _location;
}
public IRemembrance getRemembrance() {
return null;
}
private void initializeGlobalAssemblyCache() throws IOException {
BufferedReader reader = gac();
String line = null;
while (null != (line = reader.readLine())) {
Matcher m = ASSEMBLY_NAME_PATTERN.matcher(line);
if (m.matches()) {
String name = m.group(1);
String version = m.group(2);
String culture = m.group(3);
String token = m.group(4);
getGlobalAssemblyCacheReference(name, version, culture, token);
}
}
_gacInitialized = true;
}
private BufferedReader gac() throws IOException {
IMonoLauncher launcher = createLauncher(IOUtilities.combinePath(getLocation(), PATH_GACUTIL));
launcher.add("-l");
Process p = launcher.launch();
return new BufferedReader(new InputStreamReader(p.getInputStream()));
}
public IAssemblyReference[] listGlobalAssemblyCache() throws IOException {
if (!_gacInitialized) {
initializeGlobalAssemblyCache();
}
return toArray(_cachedGacReferences.values());
}
//@Override
public boolean isDotnet() {
return false;
}
}