package jetbrains.mps.internal.make.runtime.script;
/*Generated by MPS */
import jetbrains.mps.make.script.IScript;
import org.apache.log4j.Logger;
import org.apache.log4j.LogManager;
import jetbrains.mps.make.facet.ITarget;
import java.util.List;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import java.util.ArrayList;
import jetbrains.mps.internal.collections.runtime.Sequence;
import jetbrains.mps.internal.collections.runtime.ISelector;
import jetbrains.mps.messages.IMessage;
import jetbrains.mps.make.script.IResult;
import jetbrains.mps.make.script.IScriptController;
import jetbrains.mps.make.resources.IResource;
import org.jetbrains.mps.openapi.util.ProgressMonitor;
import jetbrains.mps.baseLanguage.closures.runtime.Wrappers;
import jetbrains.mps.internal.collections.runtime.ITranslator2;
import java.util.Iterator;
import jetbrains.mps.baseLanguage.closures.runtime.YieldingIterator;
import jetbrains.mps.make.facet.ITargetEx2;
import java.util.Map;
import jetbrains.mps.internal.collections.runtime.MapSequence;
import java.util.HashMap;
import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes;
import jetbrains.mps.make.script.IJobMonitor;
import jetbrains.mps.internal.collections.runtime.ILeftCombinator;
import jetbrains.mps.internal.collections.runtime.IWhereFilter;
import jetbrains.mps.make.facet.ITargetEx;
import jetbrains.mps.make.script.IFeedback;
import jetbrains.mps.make.script.IJob;
import jetbrains.mps.smodel.TimeOutRuntimeException;
import jetbrains.mps.make.script.IConfigMonitor;
import jetbrains.mps.make.script.IConfig;
import jetbrains.mps.make.script.IPropertiesPool;
import java.util.Set;
import jetbrains.mps.make.facet.IFacet;
import jetbrains.mps.internal.collections.runtime.SetSequence;
import java.util.HashSet;
import jetbrains.mps.make.resources.IPropertiesIO;
import java.io.IOException;
import jetbrains.mps.make.facet.FacetRegistry;
import jetbrains.mps.make.resources.IPropertiesPersistence;
import jetbrains.mps.make.resources.IPropertiesAccessor;
import jetbrains.mps.make.resources.IResourceWithProperties;
public class Script implements IScript {
private static Logger LOG = LogManager.getLogger(Script.class);
public static final ITarget.Name TIME_STATISTIC_RESULT_NAME = new ITarget.Name("TIME_STATISTIC");
private ITarget.Name startingTarget;
private ITarget.Name finalTarget;
private TargetRange targetRange;
private List<ValidationError> errors = ListSequence.fromList(new ArrayList<ValidationError>());
private boolean validated = false;
public Script(TargetRange targetRange, ITarget.Name defaultTargetName) {
this.targetRange = targetRange;
this.finalTarget = defaultTargetName;
}
public Script(TargetRange targetRange, ITarget.Name finalTarget, ITarget.Name startingTarget) {
this.targetRange = targetRange;
this.finalTarget = finalTarget;
this.startingTarget = startingTarget;
}
public void validate() {
ListSequence.fromList(errors).clear();
if (startingTarget != null && !(targetRange.hasTarget(startingTarget))) {
error(startingTarget, "unknown starting target: " + startingTarget);
}
if (!(targetRange.hasTarget(finalTarget))) {
error(finalTarget, "unknown final target: " + finalTarget);
}
if (targetRange.hasCycles()) {
error(this, "cycle(s) detected: " + targetRange.cycles());
}
if (startingTarget != null && !(Sequence.fromIterable(targetRange.targetAndSortedPrecursors(finalTarget)).select(new ISelector<ITarget, ITarget.Name>() {
public ITarget.Name select(ITarget t) {
return t.getName();
}
}).contains(startingTarget))) {
error(this, "invalid starting target: " + startingTarget);
}
validated = true;
}
public void invalidate() {
this.validated = false;
}
@Override
public boolean isValid() {
return validated && ListSequence.fromList(errors).isEmpty();
}
@Override
public Iterable<IMessage> validationErrors() {
return ListSequence.fromList(errors).ofType(IMessage.class);
}
@Override
public Iterable<ITarget> allTargets() {
return targetRange.sortedTargets();
}
@Override
public ITarget finalTarget() {
ITarget trg = targetRange.getTarget(finalTarget);
if (trg == null) {
LOG.error("no such target: " + finalTarget);
}
return trg;
}
@Override
public ITarget startingTarget() {
if (startingTarget == null) {
return null;
}
ITarget trg = targetRange.getTarget(startingTarget);
if (trg == null) {
LOG.error("no such target: " + startingTarget);
}
return trg;
}
@Override
public String toString() {
return "Script<" + finalTarget + ">";
}
private void error(Object o, String message) {
LOG.debug(message);
ListSequence.fromList(this.errors).addElement(new ValidationError(o, message));
}
@Override
public IResult execute(IScriptController controller, Iterable<? extends IResource> scriptInput, ProgressMonitor monitor) {
monitor.start("", 20);
try {
validate();
if (!(isValid())) {
LOG.error("attempt to execute invalid script");
throw new IllegalStateException("invalid script");
}
monitor.advance(1);
final Wrappers._T<ITarget.Name> waitFor = new Wrappers._T<ITarget.Name>(startingTarget);
Iterable<ITarget> toExecute = Sequence.fromIterable(targetRange.targetAndSortedPrecursors(finalTarget)).translate(new ITranslator2<ITarget, ITarget>() {
public Iterable<ITarget> translate(final ITarget tn) {
return new Iterable<ITarget>() {
public Iterator<ITarget> iterator() {
return new YieldingIterator<ITarget>() {
private int __CP__ = 0;
protected boolean moveToNext() {
__loop__:
do {
__switch__:
switch (this.__CP__) {
case -1:
assert false : "Internal error";
return false;
case 2:
if (waitFor.value != null) {
this.__CP__ = 3;
break;
}
this.__CP__ = 7;
break;
case 4:
if (waitFor.value.equals(tn.getName())) {
this.__CP__ = 5;
break;
}
this.__CP__ = 1;
break;
case 8:
this.__CP__ = 1;
this.yield(tn);
return true;
case 0:
this.__CP__ = 2;
break;
case 3:
this.__CP__ = 4;
break;
case 5:
waitFor.value = null;
this.__CP__ = 1;
break;
case 7:
this.__CP__ = 8;
break;
default:
break __loop__;
}
} while (true);
return false;
}
};
}
};
}
});
LOG.debug("Beginning to execute script");
CompositeResult results = new CompositeResult();
Script.ParametersPool pool = new Script.ParametersPool();
LOG.debug("Initializing");
IScriptController ctl = (controller != null ? controller : new IScriptController.Stub());
ctl.setup(pool, toExecute, scriptInput);
monitor.advance(1);
monitor.step("Configuring");
this.configureTargets(ctl, toExecute, pool, results);
if (!(results.isSucessful())) {
return results;
}
monitor.advance(1);
this.executeTargets(ctl, toExecute, scriptInput, pool, results, monitor.subTask(17));
if (!(results.isSucessful())) {
return results;
}
LOG.debug("Finished executing script");
return results;
} finally {
monitor.done();
}
}
private int workEstimate(ITarget target) {
if (target instanceof ITargetEx2) {
return ((ITargetEx2) target).workEstimate();
}
return (target.requiresInput() || target.producesOutput() ? 100 : 10);
}
private void executeTargets(final IScriptController ctl, final Iterable<ITarget> toExecute, final Iterable<? extends IResource> scriptInput, final Script.ParametersPool pool, final CompositeResult results, final ProgressMonitor monitor) {
final Map<ITarget.Name, Long> timeStatistic = MapSequence.fromMap(new HashMap<ITarget.Name, Long>());
// add time statistic result first - in composite result output() is the last one
results.addResult(TIME_STATISTIC_RESULT_NAME, new IResult.SUCCESS(Sequence.<IResource>singleton(new TimeStatisticResource(timeStatistic))));
ctl.runJobWithMonitor(new _FunctionTypes._void_P1_E0<IJobMonitor>() {
public void invoke(final IJobMonitor monit) {
monitor.start("", Sequence.fromIterable(toExecute).foldLeft(0, new ILeftCombinator<ITarget, Integer>() {
public Integer combine(Integer s, ITarget it) {
return s + workEstimate(it);
}
}));
try {
with_targets:
for (final ITarget trg : Sequence.fromIterable(toExecute)) {
LOG.debug("Executing " + trg.getName());
try {
Iterable<ITarget> impre = targetRange.immediatePrecursors(trg.getName());
Iterable<IResource> preInput = Sequence.fromIterable(impre).select(new ISelector<ITarget, IResult>() {
public IResult select(ITarget t) {
return results.getResult(t.getName());
}
}).translate(new ITranslator2<IResult, IResource>() {
public Iterable<IResource> translate(IResult r) {
return r.output();
}
});
Iterable<? extends IResource> allinput = (Sequence.fromIterable(impre).isEmpty() ? scriptInput : preInput);
Iterable<IResource> rawInput = Sequence.fromIterable(allinput).distinct().ofType(IResource.class).toListSequence();
LOG.debug("Raw input: " + rawInput);
Iterable<IResource> input = (Iterable<IResource>) Sequence.fromIterable(rawInput).where(new IWhereFilter<IResource>() {
public boolean accept(final IResource res) {
return Sequence.fromIterable(trg.expectedInput()).any(new IWhereFilter<Class<? extends IResource>>() {
public boolean accept(Class<? extends IResource> ifc) {
return ifc.isInstance(res);
}
});
}
}).toListSequence();
LOG.debug("Input: " + input);
if (trg.requiresInput()) {
if (Sequence.fromIterable(input).isEmpty()) {
if (trg instanceof ITargetEx && ((ITargetEx) trg).isOptional()) {
LOG.info("No input. Skipping optional target.");
results.addResult(trg.getName(), new IResult.SUCCESS(null));
continue with_targets;
} else {
LOG.debug("No input. Stopping");
monit.reportFeedback(new IFeedback.ERROR("Error executing target " + trg.getName() + " : no input. Stopping"));
results.addResult(trg.getName(), new IResult.FAILURE(null));
return;
}
}
}
ProgressMonitor subMonitor = monitor.subTask(workEstimate(trg));
ctl.useMonitor(subMonitor);
IJob job = trg.createJob();
long startTime = System.currentTimeMillis();
IResult jr;
try {
jr = job.execute(Sequence.fromIterable(input).where(new IWhereFilter<IResource>() {
public boolean accept(IResource it) {
return !(monit.stopRequested());
}
}), monit, new Script.PropertiesAccessor(pool), subMonitor);
} finally {
MapSequence.fromMap(timeStatistic).put(trg.getName(), ((MapSequence.fromMap(timeStatistic).containsKey(trg.getName()) ? MapSequence.fromMap(timeStatistic).get(trg.getName()) : 0)) + (System.currentTimeMillis() - startTime));
}
if (!(trg.producesOutput())) {
// ignore the output
jr = new Script.SubsOutputResult(jr, (trg.requiresInput() ? Sequence.fromIterable(rawInput).subtract(Sequence.fromIterable(input)) : rawInput));
}
results.addResult(trg.getName(), jr);
if (!(jr.isSucessful()) || monit.stopRequested()) {
monit.reportFeedback((jr.isSucessful() ? new IFeedback.INFORMATION("Cancelled by user") : new IFeedback.ERROR("Error executing target " + trg.getName())));
LOG.debug((jr.isSucessful() ? "Stop requested" : "Execution failed"));
return;
}
ctl.useMonitor(null);
monitor.advance(0);
} catch (TimeOutRuntimeException to) {
LOG.debug("Timeout executing target " + trg.getName(), to);
monit.reportFeedback(new IFeedback.ERROR("Target execution aborted " + trg.getName(), to));
results.addResult(trg.getName(), new IResult.FAILURE(null));
return;
} catch (RuntimeException rex) {
LOG.debug("Exception executing target " + trg.getName(), rex);
monit.reportFeedback(new IFeedback.ERROR("Exception executing target " + trg.getName(), rex));
results.addResult(trg.getName(), new IResult.FAILURE(null));
return;
} catch (Throwable th) {
String msg = String.format("Exception %s while executing target %s", th.getClass().getName(), trg.getName());
LOG.error(msg, th);
monit.reportFeedback(new IFeedback.ERROR(msg));
results.addResult(trg.getName(), new IResult.FAILURE(null));
return;
}
}
} finally {
monitor.done();
}
}
});
}
private void configureTargets(IScriptController ctl, final Iterable<ITarget> toExecute, final Script.ParametersPool pool, final CompositeResult results) {
ctl.runConfigWithMonitor(new _FunctionTypes._void_P1_E0<IConfigMonitor>() {
public void invoke(IConfigMonitor cmon) {
for (ITarget trg : Sequence.fromIterable(toExecute)) {
try {
LOG.debug("Configuring " + trg.getName());
IConfig cfg = trg.createConfig();
if (cfg != null && !(cfg.configure(cmon, new Script.PropertiesAccessor(pool)))) {
LOG.debug("Configuration failed for target " + trg.getName());
cmon.reportFeedback(new IFeedback.ERROR("Configuration failed for target " + trg.getName()));
results.addResult(trg.getName(), new IResult.FAILURE(null));
return;
}
} catch (RuntimeException rex) {
LOG.error("Exception configuring target " + trg.getName(), rex);
cmon.reportFeedback(new IFeedback.ERROR("Exception configuring target " + trg.getName()));
results.addResult(trg.getName(), new IResult.FAILURE(null));
return;
}
}
}
});
}
private class ParametersPool implements IPropertiesPool {
private Map<ITarget.Name, Object> cache = MapSequence.fromMap(new HashMap<ITarget.Name, Object>());
private Map<ITarget.Name, Object> copyFrom;
public ParametersPool() {
}
@Override
public <T> T properties(ITarget.Name target, Class<T> cls) {
if (!(MapSequence.fromMap(cache).containsKey(target))) {
if (targetRange.hasTarget(target)) {
T vars;
if (!(MapSequence.fromMap(copyFrom).containsKey(target))) {
vars = targetRange.getTarget(target).createParameters(cls);
} else {
T orig = null;
Object available = MapSequence.fromMap(copyFrom).get(target);
try {
orig = cls.cast(available);
} catch (ClassCastException cce) {
// ignore, just assume the original value is null
Script.LOG.debug("can't cast original parameters to required class [" + cls.getName() + "]");
Script.LOG.debug("requested class's classloader " + cls.getClassLoader() + "@" + System.identityHashCode(cls.getClassLoader()));
Script.LOG.debug("original object's classloader " + available.getClass().getClassLoader() + "@" + System.identityHashCode(available.getClass().getClassLoader()));
}
vars = targetRange.getTarget(target).createParameters(cls, orig);
}
MapSequence.fromMap(cache).put(target, vars);
} else {
return null;
}
}
return cls.cast(MapSequence.fromMap(cache).get(target));
}
@Override
public boolean hasProperties(ITarget.Name target) {
return MapSequence.fromMap(cache).containsKey(target) || MapSequence.fromMap(copyFrom).containsKey(target);
}
@Override
public void setPredecessor(IPropertiesPool ppool) {
if (ppool != null) {
this.copyFrom = ((Script.ParametersPool) ppool).cache;
}
}
}
private class PropertiesWithBackstore implements IPropertiesPool {
private final IPropertiesPool transProps;
private final IPropertiesPool persProps = new Script.ParametersPool();
private final Set<IFacet.Name> loadedFacets = SetSequence.fromSet(new HashSet<IFacet.Name>());
private final IPropertiesIO propio;
private Map<String, String> rawProps;
public PropertiesWithBackstore(IPropertiesPool transProps, IPropertiesIO propio) {
this.transProps = transProps;
this.propio = propio;
init();
}
@Override
public void setPredecessor(IPropertiesPool ppool) {
if (ppool instanceof Script.PropertiesWithBackstore) {
ppool = ((Script.PropertiesWithBackstore) ppool).transProps;
}
transProps.setPredecessor(ppool);
}
@Override
public <T> T properties(ITarget.Name target, Class<T> cls) {
if (transProps.hasProperties(target)) {
return transProps.properties(target, cls);
}
this.loadProperties(target.parentName());
return persProps.<T>properties(target, cls);
}
@Override
public boolean hasProperties(ITarget.Name target) {
if (transProps.hasProperties(target)) {
return true;
}
loadProperties(target.parentName());
return persProps.hasProperties(target);
}
private void init() {
try {
this.rawProps = propio.readProperties();
} catch (IOException ignore) {
}
}
private void loadProperties(IFacet.Name facetName) {
if (!(SetSequence.fromSet(loadedFacets).contains(facetName))) {
IFacet fct = FacetRegistry.getInstance().lookup(facetName);
if (fct != null) {
IPropertiesPersistence pp = fct.propertiesPersistence();
if (pp != null) {
pp.loadValues(rawProps, persProps);
}
}
SetSequence.fromSet(loadedFacets).addElement(facetName);
}
}
}
private class PropertiesAccessor implements IPropertiesAccessor {
private Map<Object, IPropertiesPool> allProperties = MapSequence.fromMap(new HashMap<Object, IPropertiesPool>());
private final IPropertiesPool transProps;
public PropertiesAccessor(IPropertiesPool transProps) {
this.transProps = transProps;
}
@Override
public IPropertiesPool global() {
return transProps;
}
@Override
public IPropertiesPool forResource(IResource res) {
if (!(res instanceof IResourceWithProperties)) {
return transProps;
}
IPropertiesIO pio = ((IResourceWithProperties) res).getProperties();
if (!(MapSequence.fromMap(allProperties).containsKey(pio.getKey()))) {
Script.PropertiesWithBackstore props = new Script.PropertiesWithBackstore(transProps, pio);
MapSequence.fromMap(allProperties).put(pio.getKey(), props);
}
return MapSequence.fromMap(allProperties).get(pio.getKey());
}
}
private static class SubsOutputResult implements IResult {
private IResult result;
private Iterable<? extends IResource> output;
public SubsOutputResult(IResult result, Iterable<? extends IResource> output) {
this.result = result;
this.output = output;
}
@SuppressWarnings(value = {"unchecked"})
@Override
public Iterable<IResource> output() {
return (Iterable<IResource>) output;
}
@Override
public boolean isSucessful() {
return result.isSucessful();
}
}
}