/*******************************************************************************
* This file is protected by Copyright.
* Please refer to the COPYRIGHT file distributed with this source distribution.
*
* This file is part of REDHAWK IDE.
*
* 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
*******************************************************************************/
package gov.redhawk.sca.rcp.internal;
import gov.redhawk.model.sca.DomainConnectionException;
import gov.redhawk.model.sca.Properties;
import gov.redhawk.model.sca.RefreshDepth;
import gov.redhawk.model.sca.ScaDocumentRoot;
import gov.redhawk.model.sca.ScaDomainManager;
import gov.redhawk.model.sca.ScaDomainManagerRegistry;
import gov.redhawk.model.sca.ScaFactory;
import gov.redhawk.model.sca.ScaPackage;
import gov.redhawk.model.sca.commands.ScaModelCommand;
import gov.redhawk.sca.IScaDomainManagerRegistryContainer;
import gov.redhawk.sca.ScaPlugin;
import gov.redhawk.sca.preferences.ScaPreferenceInitializer;
import java.io.IOException;
import java.net.URI;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.transaction.RunnableWithResult;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.emf.transaction.util.TransactionUtil;
/**
*
*/
public class ScaDomainManagerRegistryContainerImpl implements IScaDomainManagerRegistryContainer {
private static ScaDomainManagerRegistryContainerImpl instance;
private ScaDomainManagerRegistry scaDomainManagerRegistry;
private Resource registryResource;
private Job startupJob;
private TransactionalEditingDomain editingDomain = TransactionalEditingDomain.Registry.INSTANCE.getEditingDomain(ScaPlugin.EDITING_DOMAIN_ID);
private ResourceSet scaModelResourceSet = this.editingDomain.getResourceSet();
/**
* Listens for changes to domain manager properties, and persists them to the
* configured preference store.
*/
private Adapter propListener = new AdapterImpl() {
@Override
public void notifyChanged(Notification msg) {
if (msg.getFeatureID(Properties.class) == ScaPackage.PROPERTIES__PROPERTY) {
switch (msg.getEventType()) {
case Notification.SET:
case Notification.ADD:
saveDomainManagerRegistryResource();
break;
default:
}
}
};
};
/**
* Listens for changes to a domain manager, and persists domain preferences
* to the configured preference store.
*/
private Adapter domainManagerListener = new AdapterImpl() {
@Override
public void notifyChanged(Notification msg) {
switch (msg.getFeatureID(ScaDomainManagerRegistry.class)) {
case ScaPackage.SCA_DOMAIN_MANAGER__AUTO_CONNECT:
case ScaPackage.SCA_DOMAIN_MANAGER__DATA_PROVIDERS_ENABLED:
case ScaPackage.SCA_DOMAIN_MANAGER__NAME:
saveDomainManagerRegistryResource();
break;
default:
}
};
};
/**
* Listens for changes to the domain manager registry, and persists domain preferences
* to the configured preference store.
*/
private Adapter domainManagerRegistrylistener = new AdapterImpl() {
@SuppressWarnings("unchecked")
@Override
public void notifyChanged(Notification msg) {
if (msg.getFeatureID(ScaDomainManagerRegistry.class) == ScaPackage.SCA_DOMAIN_MANAGER_REGISTRY__DOMAINS) {
switch (msg.getEventType()) {
case Notification.ADD:
saveDomainManagerRegistryResource();
ScaDomainManager domain = (ScaDomainManager) msg.getNewValue();
addDomainManagerPropertiesListeners(domain);
break;
case Notification.ADD_MANY:
saveDomainManagerRegistryResource();
List<ScaDomainManager> domains = (List<ScaDomainManager>) msg.getNewValue();
for (ScaDomainManager mgr : domains) {
addDomainManagerPropertiesListeners(mgr);
}
break;
case Notification.REMOVE:
saveDomainManagerRegistryResource();
domain = (ScaDomainManager) msg.getOldValue();
removeDomainManagerPropertiesListeners(domain);
break;
case Notification.REMOVE_MANY:
saveDomainManagerRegistryResource();
domains = (List<ScaDomainManager>) msg.getOldValue();
for (ScaDomainManager mgr : domains) {
removeDomainManagerPropertiesListeners(mgr);
}
break;
default:
}
}
};
};
public void activate() {
loadScaModel(null);
connectOnStartup();
}
public void dispose() {
if (this.scaDomainManagerRegistry != null) {
ScaModelCommand.execute(this.scaDomainManagerRegistry, new ScaModelCommand() {
@Override
public void execute() {
if (registryResource != null) {
Resource resource = registryResource;
registryResource = null;
if (resource != null) {
try {
resource.save(null);
} catch (IOException e) {
ScaPlugin.getDefault().getLog().log(new Status(Status.ERROR, ScaPlugin.getPluginId(), "Failed to save Domain connections.", e));
}
}
}
ScaDomainManagerRegistry registry = scaDomainManagerRegistry;
registry.dispose();
scaDomainManagerRegistry = null;
if (editingDomain != null) {
// Do not dispose since it is a statically mapped editing domain
// editingDomain.dispose();
editingDomain = null;
}
}
});
}
if (this.startupJob != null) {
this.startupJob.cancel();
this.startupJob = null;
}
}
private ScaDomainManagerRegistryContainerImpl() {
//use singleton only
}
public static ScaDomainManagerRegistryContainerImpl getInstance() {
if (instance == null) {
instance = new ScaDomainManagerRegistryContainerImpl();
}
return instance;
}
@Override
public ScaDomainManagerRegistry getRegistry(Object context) {
return scaDomainManagerRegistry;
}
private void loadScaModel(Object context) {
try {
final URI fileUri = ScaPlugin.getDefault().getStateLocation().append("domains.sca").toFile().toURI();
final org.eclipse.emf.common.util.URI uri = org.eclipse.emf.common.util.URI.createURI(fileUri.toString());
try {
this.registryResource = this.scaModelResourceSet.getResource(uri, true);
} catch (final Exception e) { // SUPPRESS CHECKSTYLE Fallback
// Clear the resource set here to remove the bad
// resource from above
this.scaModelResourceSet.getResources().clear();
this.registryResource = this.scaModelResourceSet.createResource(uri, ScaPackage.eCONTENT_TYPE);
}
} catch (final IllegalStateException e1) {
// This can be thrown by the getStateLocation() call if
// the -noData option is specified. Therefore we will
// load into memory
this.registryResource = this.scaModelResourceSet.createResource(org.eclipse.emf.common.util.URI.createURI("virtual://instanceDomains.sca"),
ScaPackage.eCONTENT_TYPE);
ScaPlugin.getDefault().getLog().log(
new Status(IStatus.WARNING, ScaPlugin.getPluginId(), "Using memory store for sca domains. Will not presist domain connections.", e1));
}
this.scaDomainManagerRegistry = ScaDomainManagerRegistry.Util.getScaDomainManagerRegistry(this.registryResource);
if (this.scaDomainManagerRegistry == null) { // SUPPRESS CHECKSTYLE DoubleCheck
this.editingDomain.getCommandStack().execute(new ScaModelCommand() {
@Override
public void execute() {
scaDomainManagerRegistry = initScaResource(registryResource);
addDomainManagerListeners();
addDomainManagerRegistryListener();
}
});
} else {
addDomainManagerListeners();
addDomainManagerRegistryListener();
}
}
/**
* @since 6.1
*/
protected void removeDomainManagerPropertiesListeners(ScaDomainManager domain) {
Properties props = domain.getConnectionPropertiesContainer();
props.eAdapters().remove(propListener);
domain.eAdapters().remove(this.domainManagerListener);
}
/**
* @since 6.1
*/
protected void addDomainManagerPropertiesListeners(ScaDomainManager domain) {
//Listen for connection properties changes
Properties props = domain.getConnectionPropertiesContainer();
if (!props.eAdapters().contains(propListener)) {
props.eAdapters().add(propListener);
}
//Listen for changes to other properties, such as domain name, auto-connect, etc.
if (!domain.eAdapters().contains(this.domainManagerListener)) {
domain.eAdapters().add(this.domainManagerListener);
}
}
private void addDomainManagerListeners() {
for (ScaDomainManager domain : this.scaDomainManagerRegistry.getDomains()) {
addDomainManagerPropertiesListeners(domain);
}
}
private void addDomainManagerRegistryListener() {
this.scaDomainManagerRegistry.eAdapters().add(this.domainManagerRegistrylistener);
}
private void saveDomainManagerRegistryResource() {
if (this.scaDomainManagerRegistry != null) {
ScaModelCommand.execute(this.scaDomainManagerRegistry, new ScaModelCommand() {
@Override
public void execute() {
if (registryResource != null) {
Resource resource = registryResource;
//ScaPlugin.this.registryResource = null;
if (resource != null) {
try {
resource.save(null);
} catch (IOException e) {
ScaPlugin.getDefault().getLog().log(new Status(Status.ERROR, ScaPlugin.getPluginId(), "Failed to save Domain connections.", e));
}
}
}
}
});
}
}
private static ScaDomainManagerRegistry initScaResource(final Resource resource) {
resource.getContents().clear();
ScaDocumentRoot root = ScaFactory.eINSTANCE.createScaDocumentRoot();
final ScaDomainManagerRegistry retVal = ScaFactory.eINSTANCE.createScaDomainManagerRegistry();
final ScaDomainManagerRegistry defaultRegistry = ScaPreferenceInitializer.getDefaultScaDomainManagerRegistry();
for (final ScaDomainManager domain : defaultRegistry.getDomains()) {
retVal.getDomains().add(EcoreUtil.copy(domain));
}
root.setDomainManagerRegistry(retVal);
resource.getContents().add(root);
return retVal;
}
private void connectOnStartup() {
this.startupJob = new Job("Connecting to domains on startup...") {
@Override
protected IStatus run(final IProgressMonitor monitor) {
try {
monitor.beginTask("Connecting to domains on startup...", IProgressMonitor.UNKNOWN);
ScaDomainManager[] domains;
try {
domains = TransactionUtil.runExclusive(editingDomain, new RunnableWithResult.Impl<ScaDomainManager[]>() {
@Override
public void run() {
setResult(scaDomainManagerRegistry.getDomains().toArray(new ScaDomainManager[scaDomainManagerRegistry.getDomains().size()]));
}
});
} catch (final InterruptedException e1) {
return Status.CANCEL_STATUS;
}
for (final ScaDomainManager domain : domains) {
if (domain.isAutoConnect()) {
final Job job = new Job("Connecting to: " + domain.getLabel()) {
@Override
protected IStatus run(final IProgressMonitor monitor) {
try {
domain.connect(monitor, RefreshDepth.SELF);
} catch (final DomainConnectionException e) {
return new Status(IStatus.ERROR, ScaPlugin.getPluginId(), "Failed to connect to domain " + domain.getLabel() + ".", e);
}
return Status.OK_STATUS;
}
};
job.schedule();
}
}
return Status.OK_STATUS;
} finally {
monitor.done();
}
}
};
this.startupJob.setPriority(Job.LONG);
this.startupJob.schedule();
}
}