/*******************************************************************************
* 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.ide.debug;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.runtime.Assert;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import CF.DataType;
import CF.ErrorNumberType;
import CF.LifeCyclePackage.ReleaseError;
import CF.ResourceFactoryPackage.CreateResourceFailure;
import CF.ResourceFactoryPackage.InvalidResourceId;
import CF.ResourceFactoryPackage.ShutdownFailure;
import gov.redhawk.model.sca.ScaAbstractComponent;
import mil.jpeojtrs.sca.scd.ComponentType;
import mil.jpeojtrs.sca.scd.SoftwareComponent;
import mil.jpeojtrs.sca.spd.Implementation;
import mil.jpeojtrs.sca.spd.SoftPkg;
import mil.jpeojtrs.sca.util.ScaResourceFactoryUtil;
/**
* @since 4.0
*/
public class SpdResourceFactory extends AbstractResourceFactory {
private final List<ScaAbstractComponent< ? >> launched = Collections.synchronizedList(new ArrayList<ScaAbstractComponent< ? >>());
private final URI spdURI;
private final String identifier;
public SpdResourceFactory(SoftPkg spd) {
this(spd.eResource().getURI(), spd.getId());
}
public SpdResourceFactory(final URI spdURI, String identifier) {
Assert.isNotNull(spdURI, "SPD URI must not be null");
Assert.isNotNull(spdURI, "Identifier must not be null");
this.spdURI = spdURI;
this.identifier = identifier;
}
/**
* @since 9.0
* @throws IllegalArgumentException The component type (per the SCD) isn't supported
*/
public static SpdResourceFactory createResourceFactory(SoftPkg spd) {
if (spd.getDescriptor() == null) {
String errorMsg = String.format("Cannot create a resource factory for SPD '%s' which has no SCD", spd.getName());
throw new IllegalArgumentException(errorMsg);
}
ComponentType type = SoftwareComponent.Util.getWellKnownComponentType(spd.getDescriptor().getComponent());
switch (type) {
case RESOURCE:
checkExecutable(spd);
return new LocalComponentFactory(spd);
case DEVICE:
return new LocalDeviceFactory(spd);
case SERVICE:
return new SpdResourceFactory(spd);
default:
String errorMsg = String.format("Invalid component type '%s' for SPD '%s'", type, spd.getName());
throw new IllegalArgumentException(errorMsg);
}
}
private static void checkExecutable(SoftPkg spd) {
for (Implementation impl : spd.getImplementation()) {
if (impl.getCode() != null && impl.isExecutable()) {
return;
}
}
throw new IllegalArgumentException("Resource has no executable implementation");
}
/**
* @since 9.0
*/
protected URI getSpdUri() {
return spdURI;
}
@Override
public String identifier() {
return this.identifier;
}
/**
* @since 9.0
*/
protected SoftPkg loadSpd() {
ResourceSet resourceSet = ScaResourceFactoryUtil.createResourceSet();
Resource spdResource = resourceSet.getResource(spdURI, true);
return SoftPkg.Util.getSoftPkg(spdResource);
}
/**
* @since 9.0
*/
protected List<ScaAbstractComponent< ? >> getLaunched() {
return launched;
}
/**
* @since 9.0
*/
protected ScaAbstractComponent< ? > getResource(String resourceId) {
String resourceIdPrefix = resourceId + ":";
synchronized (launched) {
Iterator<ScaAbstractComponent< ? >> iter = this.launched.iterator();
while (iter.hasNext()) {
ScaAbstractComponent< ? > comp = iter.next();
if (comp.isDisposed()) {
iter.remove();
continue;
}
if (!comp.isSetIdentifier()) {
continue;
}
String id = comp.getIdentifier();
if (id.equals(resourceId) || id.startsWith(resourceIdPrefix)) {
return comp;
}
}
}
return null;
}
@Override
public void releaseResource(String resourceId) throws InvalidResourceId {
ScaAbstractComponent< ? > comp = getResource(resourceId);
if (comp == null) {
throw new InvalidResourceId("No resource of id: " + resourceId);
}
try {
comp.releaseObject();
} catch (ReleaseError e) {
// PASS
}
launched.remove(comp);
}
@Override
public void shutdown() throws ShutdownFailure {
synchronized (this.launched) {
Iterator<ScaAbstractComponent< ? >> iter = this.launched.iterator();
while (iter.hasNext()) {
ScaAbstractComponent< ? > comp = iter.next();
if (comp.isDisposed()) {
iter.remove();
}
}
// SCA 2.2.2, 3.1.3.1.7.5.3.5 - Exception if all resources have not been released
if (!this.launched.isEmpty()) {
throw new ShutdownFailure("Some resources have not been released");
}
}
super.shutdown();
}
/**
* @since 9.0
*/
@Override
protected CF.Resource createInstance(final String compID, final DataType[] qualifiers, final String launchMode, String implementation)
throws CreateResourceFailure {
final SoftPkg spd = loadSpd();
ComponentType type = SoftwareComponent.Util.getWellKnownComponentType(spd.getDescriptor().getComponent());
switch (type) {
case SERVICE:
throw new CreateResourceFailure(ErrorNumberType.CF_ENOTSUP, "Launching services is not supported");
default:
throw new CreateResourceFailure(ErrorNumberType.CF_ENOTSUP, "Launching this component type is not supported");
}
}
}