/**
* Copyright (c) Red Hat, Inc., contributors and others 2013 - 2014. All rights reserved
*
* Licensed under the Eclipse Public License version 1.0, available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.jboss.tools.forge.core.furnace;
import java.io.Closeable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Platform;
import org.jboss.forge.furnace.Furnace;
import org.jboss.forge.furnace.repositories.AddonRepositoryMode;
import org.jboss.forge.furnace.se.FurnaceFactory;
import org.jboss.forge.furnace.util.AddonCompatibilityStrategies;
import org.jboss.tools.forge.core.furnace.repository.IFurnaceRepository;
import org.jboss.tools.forge.core.internal.ForgeCorePlugin;
import org.jboss.tools.forge.core.internal.furnace.CompositeFurnaceClassLoader;
import org.jboss.tools.forge.core.internal.furnace.repository.FurnaceRepositoryManager;
import org.jboss.tools.forge.core.preferences.ForgeCorePreferences;
import org.osgi.framework.Bundle;
import org.osgi.framework.wiring.BundleWiring;
import bootpath.BootpathMarker;
public class FurnaceProvider {
public static final FurnaceProvider INSTANCE = new FurnaceProvider();
private static final String RUNTIME_PLUGIN_ID = "org.jboss.tools.forge.runtime";
private FurnaceProvider() {
}
public Furnace createFurnace() throws Exception {
BundleWiring wiring = ForgeCorePlugin.getDefault().getBundle()
.adapt(BundleWiring.class);
Collection<String> entries = wiring.listResources("bootpath", "*.jar",
BundleWiring.LISTRESOURCES_RECURSE);
Collection<URL> resources = new HashSet<>();
File jarDir = File.createTempFile("forge", "jars");
if (entries != null)
for (String resource : entries) {
URL jar = BootpathMarker.class.getResource("/" + resource);
if (jar != null) {
resources.add(copy(jarDir, resource, jar.openStream()));
}
}
ClassLoader furnaceLoader = new URLClassLoader(
resources.toArray(new URL[resources.size()]), null);
// add repositories from the furnace repository extension point
FurnaceRepositoryManager repositoryManager = FurnaceRepositoryManager
.getDefault();
List<IFurnaceRepository> repos = repositoryManager.getRepositories();
ArrayList<ClassLoader> loaders = new ArrayList<>();
loaders.add(FurnaceProvider.class.getClassLoader()); // this loader
// needs to be
// checked first
loaders.addAll(repositoryManager.getClassLoaders());
CompositeFurnaceClassLoader compositeLoader = new CompositeFurnaceClassLoader(
loaders);
Furnace furnace = FurnaceFactory.getInstance(compositeLoader,
furnaceLoader);
/*
* These native repositories need to be added before extensions due to
* JBDS requirements.
*/
Bundle runtimeBundle = Platform.getBundle(RUNTIME_PLUGIN_ID);
File bundleFile = FileLocator.getBundleFile(runtimeBundle);
furnace.addRepository(AddonRepositoryMode.IMMUTABLE, new File(
bundleFile, "addon-repository"));
for (IFurnaceRepository repo : repos) {
furnace.addRepository(repo.getMode(), repo.getRepositoryDirectory());
}
/*
* The user-defined addon directory should be loaded last, so that
* same-versioned addons always come from the built in repositories when
* conflicts occur.
*/
furnace.addRepository(AddonRepositoryMode.MUTABLE, new File(
ForgeCorePreferences.INSTANCE.getAddonDir()));
// Using a lenient addon compatibility strategy
furnace.setAddonCompatibilityStrategy(AddonCompatibilityStrategies.LENIENT);
return furnace;
}
public void startFurnace() {
try {
if (!FurnaceService.INSTANCE.isFurnaceSet()) {
FurnaceService.INSTANCE.setFurnace(createFurnace());
}
FurnaceService.INSTANCE.start();
} catch (Exception e) {
ForgeCorePlugin.log(e);
}
}
private URL copy(File directory, String name, InputStream input)
throws IOException {
File outputFile = new File(directory, name);
FileOutputStream output = null;
try {
directory.delete();
outputFile.getParentFile().mkdirs();
outputFile.createNewFile();
output = new FileOutputStream(outputFile);
final byte[] buffer = new byte[4096];
int read = 0;
while ((read = input.read(buffer)) != -1) {
output.write(buffer, 0, read);
}
output.flush();
} catch (Exception e) {
throw new RuntimeException("Could not write out jar file " + name,
e);
} finally {
close(input);
close(output);
}
return outputFile.toURI().toURL();
}
private void close(Closeable closeable) {
try {
if (closeable != null) {
closeable.close();
}
} catch (Exception e) {
throw new RuntimeException("Could not close stream", e);
}
}
}