blob: b527ed3845f9f3016bfb7b2576660e1b76a52791 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2007 Boeing.
* 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:
* Boeing - initial API and implementation
*******************************************************************************/
package org.eclipse.osee.ote.runtimemanager;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.logging.Level;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.osee.framework.core.operation.AbstractOperation;
import org.eclipse.osee.framework.logging.OseeLog;
import org.eclipse.osee.framework.plugin.core.util.Jobs;
import org.eclipse.osee.framework.ui.plugin.workspace.SafeWorkspaceAccess;
import org.eclipse.osee.framework.ui.workspacebundleloader.JarChangeResourceListener;
import org.eclipse.osee.ote.core.BundleInfo;
import org.eclipse.osee.ote.core.OteBundleLocator;
import org.eclipse.osee.ote.runtimemanager.container.OteClasspathContainer;
import org.eclipse.osee.ote.runtimemanager.internal.ProjectChangeResourceListener;
import org.eclipse.osee.ote.runtimemanager.internal.RuntimeBundleServer;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTracker;
/**
* @author Robert A. Fisher
* @author Andrew M. Finkbeiner
*/
public class SafeWorkspaceTracker extends ServiceTracker implements OteBundleLocator {
private JarChangeResourceListener<OteSystemLibsNature> systemLibResourceListener;
private JarChangeResourceListener<OteSystemLibsNature> precompiledResourceListener;
private JarChangeResourceListener<OteUserLibsNature> userLibResourceListener;
private LibJarListener<OteSystemLibsNature> systemLibListener;
private PrecompiledListener precompiledListener;
private LibJarListener<OteUserLibsNature> userLibListener;
private ProjectChangeResourceListener projectChangeResourceListener;
private RuntimeBundleServer bundleServer;
private SafeWorkspaceAccess service;
private final BundleContext context;
public SafeWorkspaceTracker(BundleContext context) {
super(context, SafeWorkspaceAccess.class.getName(), null);
this.context = context;
}
@Override
public Object addingService(ServiceReference reference) {
this.systemLibListener = new LibJarListener<>();
this.userLibListener = new LibJarListener<>();
this.precompiledListener = new PrecompiledListener();
this.systemLibResourceListener =
new JarChangeResourceListener<OteSystemLibsNature>(OteSystemLibsNature.NATURE_ID, systemLibListener);
this.userLibResourceListener =
new JarChangeResourceListener<OteUserLibsNature>(OteUserLibsNature.NATURE_ID, userLibListener);
this.precompiledResourceListener = new JarChangeResourceListener<>(OteSystemLibsNature.NATURE_ID, precompiledListener);
this.projectChangeResourceListener = new ProjectChangeResourceListener();
service = (SafeWorkspaceAccess) context.getService(reference);
slowLoadingJars();
precompiledListener.runCheckInThread();
return super.addingService(reference);
}
private void slowLoadingJars() {
Jobs.runInJob(new LocateWorkspaceBundles("Locating Workspace Bundles", RuntimeManager.BUNDLE_ID), false);
}
private class LocateWorkspaceBundles extends AbstractOperation {
public LocateWorkspaceBundles(String operationName, String pluginId) {
super(operationName, pluginId);
}
@SuppressWarnings("rawtypes")
@Override
protected void doWork(IProgressMonitor monitor) throws Exception {
IWorkspace workspace = service.getWorkspace();
try {
scrapeAllLibs();
} catch (CoreException ex) {
OseeLog.log(RuntimeManager.class, Level.SEVERE, ex);
}
workspace.addResourceChangeListener(systemLibResourceListener);
workspace.addResourceChangeListener(userLibResourceListener);
workspace.addResourceChangeListener(precompiledResourceListener);
SafeWorkspaceTracker.this.bundleServer = new RuntimeBundleServer(SafeWorkspaceTracker.this);
context.registerService(OteBundleLocator.class.getName(), SafeWorkspaceTracker.this, new Hashtable());
OteClasspathContainer.refreshAll();
}
}
private void scrapeAllLibs() throws CoreException {
for (OteSystemLibsNature nature : OteSystemLibsNature.getWorkspaceProjects()) {
for (URL url : nature.getBundles()) {
systemLibListener.handleBundleAdded(url);
}
projectChangeResourceListener.addProject(nature.getProject());
}
for (OteUserLibsNature nature : OteUserLibsNature.getWorkspaceProjects()) {
for (URL url : nature.getBundles()) {
userLibListener.handleBundleAdded(url);
}
projectChangeResourceListener.addProject(nature.getProject());
}
}
@Override
public synchronized void close() {
IWorkspace workspace = service.getWorkspace();
if (workspace != null) {
workspace.removeResourceChangeListener(systemLibResourceListener);
workspace.removeResourceChangeListener(userLibResourceListener);
workspace.removeResourceChangeListener(precompiledResourceListener);
}
super.close();
}
/**
* Returns a list of URL's to workspace jars to be used for the test server. The collection returned is a combination
* of all the user libraries and any system libraries that weren't already supplied in the user libraries. The
* workspace is considered to have runtime libraries only if there are system libraries present. Subsequently, if no
* system libraries are in the workspace then this method will return an empty collection.
*
* @return runtime library bundle infos
*/
@Override
public Collection<BundleInfo> getRuntimeLibs() throws IOException, CoreException {
Collection<URL> userLibUrls = getUserLibUrls();
Collection<URL> systemLibUrls = getSystemLibUrls();
// If there are no system libs, then claim no runtime libs
if (!systemLibUrls.isEmpty()) {
return getRuntimeLibs(systemLibUrls, userLibUrls);
} else {
return Collections.emptyList();
}
}
private Collection<BundleInfo> getRuntimeLibs(Collection<URL> systemLibUrls, Collection<URL> userLibUrls) throws IOException {
Map<String, BundleInfo> runtimeMap = new HashMap<>();
Collection<BundleInfo> runtimeInfos = new LinkedList<>();
// First add all of the system libraries to the map
for (URL url : systemLibUrls) {
String symbolicName = getBundleNameFromJar(url);
runtimeMap.put(symbolicName, new BundleInfo(url, bundleServer.getClassServerPath(), true));
}
// Now add the user libraries so any system library with the same name
// gets replaced
for (URL url : userLibUrls) {
String symbolicName = getBundleNameFromJar(url);
runtimeMap.put(symbolicName, new BundleInfo(url, bundleServer.getClassServerPath(), false));
}
runtimeInfos.addAll(runtimeMap.values());
return runtimeInfos;
}
/**
* Returns a list of URL's to all system libraries in the workspace regardless of ones that are supplied in user
* libraries.
*
* @return system library URL's
*/
public Collection<URL> getSystemLibUrls() throws CoreException {
Collection<URL> libs = new LinkedList<>();
for (OteSystemLibsNature systemNature : OteSystemLibsNature.getWorkspaceProjects()) {
libs.addAll(systemNature.getBundles());
}
return libs;
}
/**
* Returns a list of URL's to all user libraries in the workspace.
*
* @return user library URL's
*/
public Collection<URL> getUserLibUrls() throws CoreException {
Collection<URL> libs = new LinkedList<>();
for (OteUserLibsNature userNature : OteUserLibsNature.getWorkspaceProjects()) {
libs.addAll(userNature.getBundles());
}
return libs;
}
private String getBundleNameFromJar(URL url) throws IOException {
File file;
try {
file = new File(url.toURI());
} catch (URISyntaxException ex) {
file = new File(url.getPath());
}
JarFile jarFile = new JarFile(file);
Manifest jarManifest = jarFile.getManifest();
return BundleInfo.generateBundleName(jarManifest);
}
/**
* Returns a list of all bundles that have been modified since the last time this was called.
*/
@Override
public Collection<BundleInfo> consumeModifiedLibs() throws IOException {
// Collection<BundleInfo> modifiedLibs = new LinkedList<>();
Set<URL> sysNewBundles = systemLibListener.consumeNewBundles();
Set<URL> sysChangedBundles = systemLibListener.consumeChangedBundles();
// Set<URL> sysRemovedBundles =
systemLibListener.consumeRemovedBundles();
Set<URL> userNewBundles = userLibListener.consumeNewBundles();
Set<URL> userChangedBundles = userLibListener.consumeChangedBundles();
// Set<URL> userRemovedBundles =
userLibListener.consumeRemovedBundles();
Collection<URL> sysNewModLibs = new ArrayList<>(sysNewBundles.size() + sysChangedBundles.size());
sysNewModLibs.addAll(sysNewBundles);
sysNewModLibs.addAll(sysChangedBundles);
Collection<URL> userNewModLibs = new ArrayList<>(userNewBundles.size() + userChangedBundles.size());
userNewModLibs.addAll(userNewBundles);
userNewModLibs.addAll(userChangedBundles);
// TODO what about removed libs?
return getRuntimeLibs(sysNewModLibs, userNewModLibs);
// // For now, return all user libs
// for (BundleInfo info : getRuntimeLibs()) {
// if (!info.isSystemLibrary()) {
// modifiedLibs.add(info);
// }
// }
//
// return modifiedLibs;
}
}