/*
* Copyright (C) 2010-2016 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package com.jpexs.decompiler.flash.exporters.script;
import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler;
import com.jpexs.decompiler.flash.EventListener;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.exporters.settings.ScriptExportSettings;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
import com.jpexs.helpers.CancellableWorker;
import com.jpexs.helpers.Helper;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author JPEXS
*/
public class AS2ScriptExporter {
private static final Logger logger = Logger.getLogger(AS2ScriptExporter.class.getName());
public List<File> exportActionScript2(SWF swf, AbortRetryIgnoreHandler handler, String outdir, ScriptExportSettings exportSettings, boolean parallel, EventListener evl) throws IOException {
return exportAS2Scripts(handler, outdir, swf.getASMs(true), exportSettings, parallel, evl);
}
public List<File> exportAS2Scripts(AbortRetryIgnoreHandler handler, String outdir, Map<String, ASMSource> asms, ScriptExportSettings exportSettings, boolean parallel, EventListener evl) throws IOException {
List<File> ret = new ArrayList<>();
if (!outdir.endsWith(File.separator)) {
outdir += File.separator;
}
Map<String, List<String>> existingNamesMap = new HashMap<>();
int cnt = 1;
List<ExportScriptTask> tasks = new ArrayList<>();
String[] keys = asms.keySet().toArray(new String[asms.size()]);
Arrays.sort(keys);
for (String key : keys) {
ASMSource asm = asms.get(key);
String currentOutDir = outdir + key + File.separator;
currentOutDir = new File(currentOutDir).getParentFile().toString() + File.separator;
List<String> existingNames = existingNamesMap.get(currentOutDir);
if (existingNames == null) {
existingNames = new ArrayList<>();
existingNamesMap.put(currentOutDir, existingNames);
}
String name = Helper.makeFileName(asm.getExportFileName());
int i = 1;
String baseName = name;
while (existingNames.contains(name)) {
i++;
name = baseName + "_" + i;
}
existingNames.add(name);
tasks.add(new ExportScriptTask(handler, cnt++, asms.size(), name, asm, currentOutDir, exportSettings, evl));
}
if (!parallel || tasks.size() < 2) {
try {
CancellableWorker.call(new Callable<Void>() {
@Override
public Void call() throws Exception {
for (ExportScriptTask task : tasks) {
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException();
}
ret.add(task.call());
}
return null;
}
}, Configuration.exportTimeout.get(), TimeUnit.SECONDS);
} catch (TimeoutException ex) {
logger.log(Level.SEVERE, Helper.formatTimeToText(Configuration.exportTimeout.get()) + " ActionScript export limit reached", ex);
} catch (ExecutionException | InterruptedException ex) {
logger.log(Level.SEVERE, "Error during AS2 export", ex);
}
} else {
ExecutorService executor = Executors.newFixedThreadPool(Configuration.getParallelThreadCount());
List<Future<File>> futureResults = new ArrayList<>();
for (ExportScriptTask task : tasks) {
Future<File> future = executor.submit(task);
futureResults.add(future);
}
try {
executor.shutdown();
if (!executor.awaitTermination(Configuration.exportTimeout.get(), TimeUnit.SECONDS)) {
logger.log(Level.SEVERE, Helper.formatTimeToText(Configuration.exportTimeout.get()) + " ActionScript export limit reached");
}
} catch (InterruptedException ex) {
} finally {
executor.shutdownNow();
}
for (int f = 0; f < futureResults.size(); f++) {
try {
if (futureResults.get(f).isDone()) {
ret.add(futureResults.get(f).get());
}
} catch (InterruptedException ex) {
} catch (ExecutionException ex) {
logger.log(Level.SEVERE, "Error during ABC export", ex);
}
}
}
return ret;
}
}