statistical-algorithms-impo.../src/main/java/org/gcube/portlets/user/statisticalalgorithmsimporter/server/generator/ProjectBuilder.java

437 lines
15 KiB
Java

package org.gcube.portlets.user.statisticalalgorithmsimporter.server.generator;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ProcessBuilder.Redirect;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpSession;
import org.apache.commons.io.FileUtils;
import org.gcube.application.framework.core.session.ASLSession;
import org.gcube.common.homelibrary.home.exceptions.InternalErrorException;
import org.gcube.common.homelibrary.home.workspace.WorkspaceFolder;
import org.gcube.common.homelibrary.home.workspace.WorkspaceItem;
import org.gcube.portlets.user.statisticalalgorithmsimporter.server.SessionUtil;
import org.gcube.portlets.user.statisticalalgorithmsimporter.server.storage.FilesStorage;
import org.gcube.portlets.user.statisticalalgorithmsimporter.shared.exception.StatAlgoImporterServiceException;
import org.gcube.portlets.user.statisticalalgorithmsimporter.shared.project.Project;
import org.gcube.portlets.user.statisticalalgorithmsimporter.shared.project.ProjectTarget;
import org.gcube.portlets.user.statisticalalgorithmsimporter.shared.workspace.ItemDescription;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author Giancarlo Panichi email: <a
* href="mailto:g.panichi@isti.cnr.it">g.panichi@isti.cnr.it</a>
*
*/
public class ProjectBuilder {
private static final String ALGORITHM_MIMETYPE = "text/plain";
private static final String ALGORITHM_DESCRIPTION = "Statistical Algorithm Java Code";
private static final String ALGORITHM_EXTENTION = ".java";
private static final String INFO_NAME = "Info";
private static final String INFO_MIMETYPE = "text/plain";
private static final String INFO_DESCRIPTION = "Info";
private static final String INFO_EXTENTION = ".txt";
private static final String PROJECT_PACKAGE_MIMETYPE = "application/zip";
private static final String PROJECT_PACKAGE_DESCRIPTION = "Statical Algorithm Project Package";
private static final String PROJECT_PACKAGE_EXTENTION = ".zip";
private static final String LOG_TXT = "log.txt";
private static final String LOG_JAR_TXT = "logjar.txt";
private static final String ECOLOGICAL_ENGINE_JAR = "ecological-engine.jar";
private static final String ECOLOGICAL_ENGINE_JAR_URL = "http://data.d4science.org/id?fileName=ecological-engine.jar&smp-id=56952e9ce4b0e2fd6457272c&contentType=application%2Fjava-archive";
private static final String ECOLOGICAL_ENGINE_SMART_EXECUTOR_JAR_URL = "http://data.d4science.org/id?fileName=ecological-engine-smart-executor.jar&smp-id=56952e9ce4b0e2fd6457272e&contentType=application%2Fjava-archive";
private static final String ECOLOGICAL_ENGINE_SMART_EXECUTOR_JAR = "ecological-engine-smart-executor.jar";
private static final String CODE_JAR_MIMETYPE = "application/java-archive";
private static final String CODE_JAR_DESCRIPTION = "Statistical Algorithm Jar";
private static final String JAR_EXTENTION = ".jar";
public static final Logger logger = LoggerFactory
.getLogger(ProjectBuilder.class);
private Project project;
private ASLSession aslSession;
private HttpSession session;
private ProjectTarget projectTarget;
private Path algorithmJava;
private Path infoTXT;
public ProjectBuilder(Project project, ASLSession aslSession,
HttpSession session) {
this.project = project;
this.aslSession = aslSession;
this.session = session;
}
private void checkInfo() throws StatAlgoImporterServiceException {
if (project == null) {
throw new StatAlgoImporterServiceException(
"Attention No Project Found!");
}
if (project.getProjectFolder() == null) {
throw new StatAlgoImporterServiceException(
"Attention No Project Folder Found!");
}
if (project.getInputData() == null) {
throw new StatAlgoImporterServiceException(
"Attention No Input Set!");
}
if (project.getInputData().getProjectInfo() == null) {
throw new StatAlgoImporterServiceException(
"Attention No Project Information Set!");
}
if (project.getInputData().getProjectInfo().getAlgorithmName() == null) {
throw new StatAlgoImporterServiceException(
"Attention No Algorithm Name Set!");
}
if (project.getMainCode() == null) {
throw new StatAlgoImporterServiceException(
"Attention No Main Code Set");
}
if (project.getInputData() == null) {
throw new StatAlgoImporterServiceException(
"Attention No Input Data Set!");
}
}
public void build() throws StatAlgoImporterServiceException {
checkInfo();
createProjectPackage();
createAlgorithm();
createIntegrationInfo();
createProjectJarFile();
SessionUtil.setProjectSession(session, project);
}
protected void createAlgorithm() throws StatAlgoImporterServiceException {
AlgorithmGenerator algorithmGenerator = new AlgorithmGenerator(project);
algorithmJava = algorithmGenerator.createAlgorithm();
FilesStorage filesStorage = new FilesStorage();
WorkspaceItem algorithmItem;
try {
algorithmItem = filesStorage.createItemOnWorkspace(aslSession
.getUsername(), Files.newInputStream(algorithmJava,
StandardOpenOption.READ), project.getInputData()
.getProjectInfo().getAlgorithmNameToClassName()
+ ALGORITHM_EXTENTION, ALGORITHM_DESCRIPTION,
ALGORITHM_MIMETYPE, project.getProjectTarget()
.getTargetFolder().getId());
} catch (IOException e) {
logger.error(e.getLocalizedMessage());
e.printStackTrace();
throw new StatAlgoImporterServiceException(e.getLocalizedMessage(),
e);
}
ItemDescription codeSource;
try {
codeSource = new ItemDescription(algorithmItem.getId(),
algorithmItem.getName(), algorithmItem.getOwner()
.getPortalLogin(), algorithmItem.getPath(),
algorithmItem.getType().name());
codeSource.setPublicLink(algorithmItem.getPublicLink(true));
} catch (InternalErrorException e) {
logger.error(e.getLocalizedMessage());
e.printStackTrace();
throw new StatAlgoImporterServiceException(e.getLocalizedMessage());
}
projectTarget.setCodeSource(codeSource);
logger.debug("ProjectTarget: " + projectTarget);
project.setProjectTarget(projectTarget);
}
private void createProjectPackage() throws StatAlgoImporterServiceException {
FilesStorage filesStorage = new FilesStorage();
filesStorage.deleteTargetFolder(aslSession.getUsername(), project
.getProjectFolder().getItemDescription().getId());
File projectPackageFile = filesStorage.zipFolder(
aslSession.getUsername(), project.getProjectFolder()
.getItemDescription().getId());
WorkspaceFolder targetFolder = filesStorage.createTargetFolder(
aslSession.getUsername(), project.getProjectFolder()
.getItemDescription().getId());
logger.debug("TargetFolder:" + targetFolder);
ItemDescription tFolder;
try {
tFolder = new ItemDescription(targetFolder.getId(),
targetFolder.getName(), targetFolder.getOwner()
.getPortalLogin(), targetFolder.getPath(),
targetFolder.getType().name());
} catch (InternalErrorException e) {
logger.error(e.getLocalizedMessage());
e.printStackTrace();
throw new StatAlgoImporterServiceException(e.getLocalizedMessage());
}
projectTarget = new ProjectTarget(tFolder);
InputStream inputStream;
try {
inputStream = Files.newInputStream(projectPackageFile.toPath(),
StandardOpenOption.READ);
} catch (IOException e) {
logger.error("Error input stream generation: "
+ e.getLocalizedMessage());
e.printStackTrace();
throw new StatAlgoImporterServiceException(e.getLocalizedMessage());
}
WorkspaceItem projectPackageItem;
try {
projectPackageItem = filesStorage.createItemOnWorkspace(
aslSession.getUsername(), inputStream, project
.getInputData().getProjectInfo().getAlgorithmNameToClassName()
+ PROJECT_PACKAGE_EXTENTION,
PROJECT_PACKAGE_DESCRIPTION, PROJECT_PACKAGE_MIMETYPE,
targetFolder.getId());
} catch (InternalErrorException e) {
logger.error(e.getLocalizedMessage());
e.printStackTrace();
throw new StatAlgoImporterServiceException(e.getLocalizedMessage());
}
logger.debug("ProjectPackageItem:" + projectPackageItem);
ItemDescription packageUrl;
try {
packageUrl = new ItemDescription(projectPackageItem.getId(),
projectPackageItem.getName(), projectPackageItem.getOwner()
.getPortalLogin(), projectPackageItem.getPath(),
projectPackageItem.getType().name());
packageUrl.setPublicLink(projectPackageItem.getPublicLink(true));
} catch (InternalErrorException e) {
logger.error(e.getLocalizedMessage());
e.printStackTrace();
throw new StatAlgoImporterServiceException(e.getLocalizedMessage());
}
projectTarget.setPackageUrl(packageUrl);
project.setProjectTarget(projectTarget);
}
private void createIntegrationInfo()
throws StatAlgoImporterServiceException {
InfoGenerator integrationInfoGenerator = new InfoGenerator(
project);
infoTXT = integrationInfoGenerator.createInfo();
FilesStorage filesStorage = new FilesStorage();
WorkspaceItem infoItem;
try {
infoItem = filesStorage.createItemOnWorkspace(
aslSession.getUsername(),
Files.newInputStream(infoTXT, StandardOpenOption.READ),
INFO_NAME + INFO_EXTENTION,
INFO_DESCRIPTION, INFO_MIMETYPE,
project.getProjectTarget().getTargetFolder().getId());
} catch (IOException e) {
logger.error(e.getLocalizedMessage());
e.printStackTrace();
throw new StatAlgoImporterServiceException(e.getLocalizedMessage(),
e);
}
ItemDescription integrationItemDescription;
try {
integrationItemDescription = new ItemDescription(infoItem.getId(),
infoItem.getName(), infoItem.getOwner().getPortalLogin(),
infoItem.getPath(), infoItem.getType().name());
integrationItemDescription.setPublicLink(infoItem
.getPublicLink(true));
} catch (InternalErrorException e) {
logger.error(e.getLocalizedMessage());
e.printStackTrace();
throw new StatAlgoImporterServiceException(e.getLocalizedMessage());
}
projectTarget.setIntegrationInfo(integrationItemDescription);
logger.debug("ProjectTarget: " + projectTarget);
project.setProjectTarget(projectTarget);
}
private void createProjectJarFile() throws StatAlgoImporterServiceException {
try {
FilesStorage storage = new FilesStorage();
Path tempDirectory = Files.createTempDirectory("StatAlgorithmsJar");
logger.debug("TempDir: " + tempDirectory);
Path ecologicalEngineJar = new File(tempDirectory.toFile(),
ECOLOGICAL_ENGINE_JAR).toPath();
storage.downloadInputFile(ECOLOGICAL_ENGINE_JAR_URL,
ecologicalEngineJar);
Path ecologicalEngineSmartExecutorJar = new File(
tempDirectory.toFile(),
ECOLOGICAL_ENGINE_SMART_EXECUTOR_JAR).toPath();
storage.downloadInputFile(ECOLOGICAL_ENGINE_SMART_EXECUTOR_JAR_URL,
ecologicalEngineSmartExecutorJar);
Path algorithmTempFile = new File(tempDirectory.toFile(), project
.getInputData().getProjectInfo().getAlgorithmNameToClassName()
+ ALGORITHM_EXTENTION).toPath();
Files.copy(algorithmJava, algorithmTempFile);
Path infoTempFile = new File(tempDirectory.toFile(),
INFO_NAME + INFO_EXTENTION)
.toPath();
Files.copy(infoTXT, infoTempFile);
createClassFile(tempDirectory);
createJarFile(tempDirectory, infoTempFile);
copyJarOnWorkspace(tempDirectory);
FileUtils.cleanDirectory(tempDirectory.toFile());
FileUtils.deleteDirectory(tempDirectory.toFile());
return;
} catch (IOException e) {
logger.error(e.getLocalizedMessage());
e.printStackTrace();
throw new StatAlgoImporterServiceException(e.getLocalizedMessage(),
e);
}
}
private void copyJarOnWorkspace(Path tempDirectory) throws StatAlgoImporterServiceException {
Path codeJar=Paths.get(tempDirectory.toString(),project.getInputData().getProjectInfo().getAlgorithmNameToClassName()
+ JAR_EXTENTION);
FilesStorage filesStorage = new FilesStorage();
WorkspaceItem codeJarItem;
try {
codeJarItem = filesStorage.createItemOnWorkspace(aslSession
.getUsername(), Files.newInputStream(codeJar,
StandardOpenOption.READ), project.getInputData().getProjectInfo().getAlgorithmNameToClassName()
+ JAR_EXTENTION, CODE_JAR_DESCRIPTION,
CODE_JAR_MIMETYPE, project.getProjectTarget()
.getTargetFolder().getId());
} catch (IOException e) {
logger.error(e.getLocalizedMessage());
e.printStackTrace();
throw new StatAlgoImporterServiceException(e.getLocalizedMessage(),
e);
}
ItemDescription codeJarItemDescription;
try {
codeJarItemDescription = new ItemDescription(codeJarItem.getId(),
codeJarItem.getName(), codeJarItem.getOwner()
.getPortalLogin(), codeJarItem.getPath(),
codeJarItem.getType().name());
codeJarItemDescription.setPublicLink(codeJarItem.getPublicLink(true));
} catch (InternalErrorException e) {
logger.error(e.getLocalizedMessage());
e.printStackTrace();
throw new StatAlgoImporterServiceException(e.getLocalizedMessage());
}
projectTarget.setCodeJar(codeJarItemDescription);
logger.debug("ProjectTarget: " + projectTarget);
project.setProjectTarget(projectTarget);
}
private void createClassFile(Path tempDirectory)
throws StatAlgoImporterServiceException {
try {
ProcessBuilder pb = new ProcessBuilder("javac", "-cp",
tempDirectory.toAbsolutePath().toString() + "/*", project
.getInputData().getProjectInfo().getAlgorithmNameToClassName()
+ ALGORITHM_EXTENTION);
pb.directory(tempDirectory.toFile());
Path logTXT = new File(tempDirectory.toFile(), LOG_TXT).toPath();
pb.redirectErrorStream(true);
pb.redirectOutput(Redirect.appendTo(logTXT.toFile()));
logger.debug("Process: " + pb.toString());
Process process = pb.start();
// Wait to get exit value
int exitValue = process.waitFor();
logger.debug("Create Algo Class: Exit Value is " + exitValue);
} catch (IOException | InterruptedException e) {
logger.error(e.getLocalizedMessage());
e.printStackTrace();
throw new StatAlgoImporterServiceException(e.getLocalizedMessage(),
e);
}
}
private void createJarFile(Path tempDirectory, Path infoTempFile)
throws StatAlgoImporterServiceException {
try {
List<String> commands = new ArrayList<>();
commands.add("jar");
commands.add("-cvf");
commands.add(project.getInputData().getProjectInfo().getAlgorithmNameToClassName()
+ JAR_EXTENTION);
DirectoryStream<Path> directoryStream = Files
.newDirectoryStream(tempDirectory);
for (Path path : directoryStream) {
if (path.toString().endsWith(".class"))
commands.add(path.getFileName().toString());
}
commands.add(infoTempFile.getFileName().toString());
ProcessBuilder pb = new ProcessBuilder(commands);
pb.directory(tempDirectory.toFile());
Path logTXT = new File(tempDirectory.toFile(), LOG_JAR_TXT)
.toPath();
pb.redirectErrorStream(true);
pb.redirectOutput(Redirect.appendTo(logTXT.toFile()));
logger.debug("Process: " + pb.toString());
Process process = pb.start();
// Wait to get exit value
int exitValue = process.waitFor();
logger.debug("Create Algo Jar: Exit Value is " + exitValue);
} catch (IOException | InterruptedException e) {
logger.error(e.getLocalizedMessage());
e.printStackTrace();
throw new StatAlgoImporterServiceException(e.getLocalizedMessage(),
e);
}
}
}