/*******************************************************************************
* Copyright (c) 2008 Vlad Dumitrescu and others. 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: Vlad Dumitrescu
*******************************************************************************/
package org.erlide.runtime.runtimeinfo;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jdt.annotation.NonNull;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
public final class RuntimeInfoCatalog implements IRuntimeInfoCatalog {
public @NonNull RuntimeInfo erlideRuntime;
public final Map<String, RuntimeInfo> runtimes;
public String defaultRuntimeName;
public RuntimeInfoCatalog() {
runtimes = Maps.newHashMap();
erlideRuntime = RuntimeInfo.NO_RUNTIME_INFO;
defaultRuntimeName = null;
}
@Override
public synchronized Collection<RuntimeInfo> getRuntimes() {
return Collections.unmodifiableCollection(runtimes.values());
}
@Override
public synchronized void setRuntimes(final Collection<RuntimeInfo> elements,
final String dfltRuntime, final String ideRuntime) {
runtimes.clear();
if (elements.isEmpty()) {
initializeRuntimesList();
}
for (final RuntimeInfo rt : elements) {
addRuntime(rt);
}
defaultRuntimeName = dfltRuntime;
if (defaultRuntimeName == null) {
setDefaultRuntimes();
}
final RuntimeInfo rt = runtimes
.get(ideRuntime != null ? ideRuntime : defaultRuntimeName);
if (rt == null) {
erlideRuntime = getDefaultRuntime();
} else {
erlideRuntime = rt;
}
Assert.isNotNull(erlideRuntime);
}
@Override
public synchronized void addRuntime(final RuntimeInfo rt) {
if (rt.getVersion().isCompatible(OLDEST_SUPPORTED_VERSION)
&& !runtimes.containsKey(rt.getName())) {
runtimes.put(rt.getName(), rt);
}
}
@Override
public synchronized Collection<String> getRuntimeNames() {
return runtimes.keySet();
}
@Override
public boolean hasRuntimeWithName(final String name) {
return runtimes.containsKey(name);
}
@Override
public @NonNull RuntimeInfo getRuntime(final String name) {
final RuntimeInfo rt = runtimes.get(name);
if (rt != null && rt.isValid()) {
return rt;
}
return RuntimeInfo.NO_RUNTIME_INFO;
}
@Override
public synchronized void removeRuntime(final String name) {
runtimes.remove(name);
if (!runtimes.isEmpty()) {
if (erlideRuntime.getName().equals(name)) {
final RuntimeInfo rt = runtimes.values().iterator().next();
erlideRuntime = rt == null ? RuntimeInfo.NO_RUNTIME_INFO : rt;
}
if (defaultRuntimeName.equals(name)) {
defaultRuntimeName = runtimes.keySet().iterator().next();
}
} else {
erlideRuntime = RuntimeInfo.NO_RUNTIME_INFO;
defaultRuntimeName = null;
}
}
@Override
public synchronized String getDefaultRuntimeName() {
return defaultRuntimeName;
}
@Override
public synchronized void setDefaultRuntime(final String name) {
defaultRuntimeName = name;
}
private synchronized void setErlideRuntime(final @NonNull RuntimeInfo runtime) {
final RuntimeInfo old = erlideRuntime;
if (!old.equals(runtime)) {
erlideRuntime = runtime;
// this creates infinite recursion!
// BackendManagerImpl.getDefault().getIdeBackend().stop();
}
}
@Override
public synchronized @NonNull RuntimeInfo getErlideRuntime() {
return erlideRuntime;
}
@Override
public synchronized @NonNull RuntimeInfo getDefaultRuntime() {
return getRuntime(getDefaultRuntimeName());
}
@Override
public RuntimeInfo getRuntime(final RuntimeVersion runtimeVersion,
final String runtimeName) {
final Collection<RuntimeInfo> vsns = VersionLocator.locateVersion(runtimeVersion,
runtimes.values(), false);
if (vsns.isEmpty()) {
return null;
} else if (vsns.size() == 1) {
return vsns.iterator().next();
} else {
for (final RuntimeInfo ri : vsns) {
if (runtimeName == null || ri.getName().equals(runtimeName)) {
return ri;
}
}
return vsns.iterator().next();
}
}
@Override
public List<String> getAllRuntimesVersions() {
final Collection<RuntimeInfo> rs = getRuntimes();
final List<String> myVersions = Lists.newArrayList();
for (final RuntimeInfo info : rs) {
final String version = info.getVersion().asMinor().toString();
if (!myVersions.contains(version)) {
myVersions.add(version);
}
}
Collections.sort(myVersions);
return myVersions;
}
/**
* If runtime is not set, try to locate one. The first one found as below is set as
* default. All "obvious" runtimes found are stored.
* <ul>
* <li>A system property <code>erlide.runtime</code> can be set to point to a
* location.</li>
* <li>A preference in the default scope <code>org.erlide.core/default_runtime</code>
* can be set to point to a location.</li>
* <li>Look for existing Erlang runtimes in a few obvious places and install them,
* choosing a suitable one as default.</li>
* </ul>
*
*/
@Override
public void initializeRuntimesList() {
final Collection<RuntimeInfo> found = RuntimeFinder.guessRuntimeLocations();
for (final RuntimeInfo info : found) {
addRuntime(info);
}
setDefaultRuntimes();
}
private void setDefaultRuntimes() {
final List<RuntimeInfo> list = new ArrayList<>(getRuntimes());
Collections.sort(list, new Comparator<RuntimeInfo>() {
@Override
public int compare(final RuntimeInfo o1, final RuntimeInfo o2) {
final int x = o2.getVersion().compareTo(o1.getVersion());
if (x != 0) {
return x;
}
return o2.getName().compareTo(o1.getName());
}
});
if (!list.isEmpty()) {
final String firstName = list.get(0).getName();
if (defaultRuntimeName == null) {
setDefaultRuntime(firstName);
}
// the erlide backend is the most recent stable version
for (final RuntimeInfo info : list) {
if (info.getVersion().isStable()) {
setErlideRuntime(info);
break;
}
}
}
}
}