package org.eclipse.equinox.internal.app;
import java.net.URL;
import java.security.AccessController;
import java.util.*;
import org.eclipse.equinox.app.IApplicationContext;
import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.application.*;
import org.osgi.service.condpermadmin.BundleSignerCondition;
import org.osgi.service.condpermadmin.ConditionInfo;
public class EclipseAppDescriptor extends ApplicationDescriptor {
static final String APP_TYPE = "eclipse.application.type";
static final String APP_DEFAULT = "eclipse.application.default";
static final String APP_TYPE_MAIN_THREAD = "main.thread";
static final String APP_TYPE_ANY_THREAD = "any.thread";
static final int FLAG_VISIBLE = 0x01;
static final int FLAG_CARD_SINGLETON_GLOGAL = 0x02;
static final int FLAG_CARD_SINGLETON_SCOPED = 0x04;
static final int FLAG_CARD_UNLIMITED = 0x08;
static final int FLAG_CARD_LIMITED = 0x10;
static final int FLAG_TYPE_MAIN_THREAD = 0x20;
static final int FLAG_TYPE_ANY_THREAD = 0x40;
static final int FLAG_DEFAULT_APP = 0x80;
private long instanceID = 0;
private ServiceRegistration sr;
private Boolean locked = Boolean.FALSE;
private final EclipseAppContainer appContainer;
private final Bundle contributor;
private final int flags;
private final int cardinality;
private final String name;
private final URL iconURL;
private final boolean[] registrationLock = new boolean[] {true};
protected EclipseAppDescriptor(Bundle contributor, String pid, String name, String iconPath, int flags, int cardinality, EclipseAppContainer appContainer) {
super(pid);
this.name = name;
this.contributor = contributor;
this.appContainer = appContainer;
this.locked = AppPersistence.isLocked(this) ? Boolean.TRUE : Boolean.FALSE;
this.flags = flags;
this.cardinality = cardinality;
URL iconResult = null;
if (iconPath != null && iconPath.length() > 0) {
if (iconPath.charAt(0) == '/')
iconPath = iconPath.substring(1);
String baseIconDir = "/";
String iconFile = iconPath;
int lastSlash = iconPath.lastIndexOf('/');
if (lastSlash > 0 && lastSlash < iconPath.length() - 1) {
baseIconDir = iconPath.substring(0, lastSlash);
iconFile = iconPath.substring(lastSlash + 1);
}
Enumeration<URL> urls = contributor.findEntries(baseIconDir, iconFile, false);
if (urls != null && urls.hasMoreElements())
iconResult = urls.nextElement();
}
this.iconURL = iconResult;
}
@Override
protected Map getPropertiesSpecific(String locale) {
return getServiceProperties();
}
@Override
protected ApplicationHandle launchSpecific(Map arguments) throws Exception {
if (getLocked().booleanValue())
throw new IllegalStateException("Cannot launch a locked application.");
EclipseAppHandle appHandle = createAppHandle(arguments);
try {
appContainer.launch(appHandle);
} catch (Throwable t) {
try {
appHandle.destroy();
} catch (Throwable destroyError) {
}
if (t instanceof Exception)
throw (Exception) t;
throw (Error) t;
}
return appHandle;
}
@Override
protected synchronized void lockSpecific() {
locked = Boolean.TRUE;
refreshProperties();
}
@Override
protected synchronized void unlockSpecific() {
locked = Boolean.FALSE;
refreshProperties();
}
void refreshProperties() {
ServiceRegistration reg = getServiceRegistration();
if (reg != null)
try {
reg.setProperties(getServiceProperties());
} catch (IllegalStateException e) {
}
}
void setServiceRegistration(ServiceRegistration sr) {
synchronized (registrationLock) {
this.sr = sr;
registrationLock[0] = sr != null;
registrationLock.notifyAll();
}
}
private ServiceRegistration getServiceRegistration() {
synchronized (registrationLock) {
if (sr == null && registrationLock[0])
try {
registrationLock.wait(1000);
} catch (InterruptedException e) {
}
return sr;
}
}
private synchronized Boolean getLocked() {
return locked;
}
Hashtable<String, Object> getServiceProperties() {
Hashtable<String, Object> props = new Hashtable<>(10);
props.put(ApplicationDescriptor.APPLICATION_PID, getApplicationId());
if (name != null)
props.put(ApplicationDescriptor.APPLICATION_NAME, name);
props.put(ApplicationDescriptor.APPLICATION_CONTAINER, Activator.PI_APP);
props.put(ApplicationDescriptor.APPLICATION_LOCATION, getLocation());
Boolean launchable = appContainer.isLocked(this) == 0 ? Boolean.TRUE : Boolean.FALSE;
props.put(ApplicationDescriptor.APPLICATION_LAUNCHABLE, launchable);
props.put(ApplicationDescriptor.APPLICATION_LOCKED, getLocked());
Boolean visible = (flags & FLAG_VISIBLE) != 0 ? Boolean.TRUE : Boolean.FALSE;
props.put(ApplicationDescriptor.APPLICATION_VISIBLE, visible);
props.put(APP_TYPE, getThreadTypeString());
if ((flags & FLAG_DEFAULT_APP) != 0)
props.put(APP_DEFAULT, Boolean.TRUE);
if (iconURL != null)
props.put(ApplicationDescriptor.APPLICATION_ICON, iconURL);
return props;
}
private String getLocation() {
if (contributor == null)
return "";
return Activator.getLocation(contributor);
}
private EclipseAppHandle createAppHandle(Map<String, Object> arguments) throws ApplicationException {
EclipseAppHandle newAppHandle = new EclipseAppHandle(getInstanceID(), arguments, this);
appContainer.lock(newAppHandle);
ServiceRegistration appHandleReg = (ServiceRegistration) AccessController.doPrivileged(appContainer.getRegServiceAction(new String[] {ApplicationHandle.class.getName(), IApplicationContext.class.getName()}, newAppHandle, newAppHandle.getServiceProperties()));
newAppHandle.setServiceRegistration(appHandleReg);
return newAppHandle;
}
EclipseAppContainer getContainerManager() {
return appContainer;
}
@Override
public boolean matchDNChain(String pattern) {
if (contributor == null)
return false;
return BundleSignerCondition.getCondition(contributor, new ConditionInfo(BundleSignerCondition.class.getName(), new String[] {pattern})).isSatisfied();
}
@Override
protected boolean isLaunchableSpecific() {
return true;
}
public void unregister() {
ServiceRegistration temp = getServiceRegistration();
if (temp != null) {
setServiceRegistration(null);
temp.unregister();
}
}
String getThreadTypeString() {
if ((flags & FLAG_TYPE_ANY_THREAD) != 0)
return APP_TYPE_ANY_THREAD;
return APP_TYPE_MAIN_THREAD;
}
int getThreadType() {
return flags & (FLAG_TYPE_ANY_THREAD | FLAG_TYPE_MAIN_THREAD);
}
int getCardinalityType() {
return flags & (FLAG_CARD_SINGLETON_GLOGAL | FLAG_CARD_SINGLETON_SCOPED | FLAG_CARD_LIMITED | FLAG_CARD_UNLIMITED);
}
int getCardinality() {
return cardinality;
}
private synchronized String getInstanceID() {
if (instanceID == Long.MAX_VALUE)
instanceID = 0;
return getApplicationId() + "." + instanceID++;
}
}