/*
* Copyright (c) 2014 Data Harmonisation Panel
*
* All rights reserved. This program and the accompanying materials are made
* available under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution. If not, see <http://www.gnu.org/licenses/>.
*
* Contributors:
* Data Harmonisation Panel <http://www.dhpanel.eu>
*/
package eu.esdihumboldt.hale.common.app;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.equinox.app.IApplication;
import org.eclipse.equinox.app.IApplicationContext;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.application.ApplicationDescriptor;
import org.osgi.service.application.ApplicationException;
import org.osgi.service.application.ApplicationHandle;
import org.osgi.util.tracker.ServiceTracker;
import eu.esdihumboldt.hale.common.app.internal.Activator;
/**
* Utilities for launching applications.
*
* @author Simon Templer
*/
public class ApplicationUtil {
/**
* Launch an application.
*
* @param application the application instance
* @param argList the application arguments
* @return the application return code
* @throws Exception if the application exits with an exception
*/
public static Object launchSyncApplication(IApplication application, final List<String> argList)
throws Exception {
String[] args = argList.size() == 0 ? null : (String[]) argList.toArray(new String[argList
.size()]);
final Map<String, Object> launchArgs = new HashMap<>(1);
if (args != null) {
launchArgs.put(IApplicationContext.APPLICATION_ARGS, args);
}
IApplicationContext context = new IApplicationContext() {
@Override
public void setResult(Object result, IApplication application) {
throw new UnsupportedOperationException();
}
@Override
public String getBrandingProperty(String key) {
return null;
}
@Override
public String getBrandingName() {
return null;
}
@Override
public String getBrandingId() {
return null;
}
@Override
public String getBrandingDescription() {
return null;
}
@Override
public Bundle getBrandingBundle() {
return null;
}
@Override
public String getBrandingApplication() {
return null;
}
@SuppressWarnings("rawtypes")
@Override
public Map getArguments() {
return launchArgs;
}
@Override
public void applicationRunning() {
// anything to do?
}
};
return application.start(context);
}
/**
* Launch an application inside the current framework.
*
* Please note that launching an application like this may fail if another
* application is running (that is a global singleton).
*
* @param appId the application identifier
* @param argList the arguments
* @return the application return value
* @throws ApplicationException if the application cannot be launched
* @throws InterruptedException if the thread was interrupted while waiting
* for the application termination
*/
public static Object launchApplication(String appId, List<String> argList)
throws ApplicationException, InterruptedException {
BundleContext context = Activator.getContext();
ServiceTracker<ApplicationDescriptor, ?> applicationDescriptors = new ServiceTracker<>(
context, ApplicationDescriptor.class.getName(), null);
applicationDescriptors.open();
try {
ServiceReference<ApplicationDescriptor> application = getApplication(
applicationDescriptors.getServiceReferences(), appId,
ApplicationDescriptor.APPLICATION_PID, false);
if (application == null) {
throw new IllegalStateException("\"" + appId + "\" does not exist or is ambigous."); //$NON-NLS-1$ //$NON-NLS-2$
}
else {
String[] args = argList.size() == 0 ? null : (String[]) argList
.toArray(new String[argList.size()]);
try {
Map<String, Object> launchArgs = new HashMap<>(1);
if (args != null) {
launchArgs.put(IApplicationContext.APPLICATION_ARGS, args);
}
ApplicationDescriptor appDesc = (context.getService(application));
ApplicationHandle handle = appDesc.launch(launchArgs);
return handle.getExitValue(0);
} finally {
context.ungetService(application);
}
}
} finally {
applicationDescriptors.close();
}
}
private static ServiceReference<ApplicationDescriptor> getApplication(
ServiceReference<ApplicationDescriptor>[] apps, String targetId, String idKey,
boolean perfectMatch) {
if (apps == null || targetId == null)
return null;
ServiceReference<ApplicationDescriptor> result = null;
boolean ambigous = false;
for (int i = 0; i < apps.length; i++) {
String id = (String) apps[i].getProperty(idKey);
if (targetId.equals(id))
return apps[i]; // always return a perfect match
if (perfectMatch)
continue;
if (id.indexOf(targetId) >= 0) {
if (result != null)
ambigous = true;
result = apps[i];
}
}
return ambigous ? null : result;
}
}