blob: 6df54d16de048b299303ee69e128e629a4677707 [file] [log] [blame]
/*****************************************************************************
*
* Copyright (c) 2016 CEA LIST.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* CEA LIST Initial API and implementation
*
*****************************************************************************/
package org.eclipse.papyrus.moka.fmi.fmu;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import org.eclipse.emf.ecore.util.BasicExtendedMetaData;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.util.ExtendedMetaData;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl;
import org.eclipse.papyrus.moka.fmi.fmumetamodel.AbstractFile;
import org.eclipse.papyrus.moka.fmi.fmumetamodel.ArchiveToUnzipInFMU;
import org.eclipse.papyrus.moka.fmi.fmumetamodel.FMUBundle;
import org.eclipse.papyrus.moka.fmi.fmumetamodel.FmumetamodelFactory;
import org.eclipse.papyrus.moka.fmi.fmumetamodel.FolderToCreateInFMU;
import org.eclipse.papyrus.moka.fmi.fmumetamodel.JavaFileProxy;
import org.eclipse.papyrus.moka.fmi.modeldescription.DocumentRoot;
import org.eclipse.papyrus.moka.fmi.modeldescription.FmiFactory;
import org.eclipse.papyrus.moka.fmi.modeldescription.FmiModelDescriptionType;
import org.eclipse.papyrus.moka.fmi.modeldescription.FmiPackage;
import org.eclipse.papyrus.moka.fmi.modeldescription.util.FmiResourceImpl;
import org.eclipse.papyrus.moka.fmi.util.FMUResourceUtil;
import org.eclipse.papyrus.moka.fmi.util.UnzipUtility;
public class FMUResource extends XMLResourceImpl {
FMUParser fmuParser;
FMUBundle fmuBundle;
public FMUParser getFmuParser() {
return fmuParser;
}
@Override
public void doLoad(InputStream inputStream, Map<?, ?> options) throws IOException {
Path tmpDirectoryPath = Files.createTempDirectory("fmuResource");
UnzipUtility.unzip(new ZipInputStream(inputStream), tmpDirectoryPath.toString(), uri.lastSegment());
fmuParser = new FMUParser(tmpDirectoryPath.toString());
createFmuBundle();
getContents().add(fmuBundle);
}
private void createFmuBundle() throws IOException {
fmuBundle = FmumetamodelFactory.eINSTANCE.createFMUBundle();
if (fmuParser.getModelDescription() != null) {
fmuBundle.setModelDescription(fmuParser.getModelDescription());
}
File fmuFolder = fmuParser.getFMUFolder();
for (File fmuChildFile : fmuFolder.listFiles()) {
switch (fmuChildFile.getName()) {
case FMUResourceUtil.FOLDER_RESOURCES:
fmuBundle.getResourcesFiles().addAll(FMUResourceUtil.createJavaFileProxies(fmuChildFile.listFiles()));
break;
case FMUResourceUtil.FOLDER_DOCUMENTATION:
fmuBundle.getDocumentationFiles()
.addAll(FMUResourceUtil.createJavaFileProxies(fmuChildFile.listFiles()));
break;
case FMUResourceUtil.FOLDER_SOURCES:
fmuBundle.getSourceFiles()
.addAll(FMUResourceUtil.createJavaFileProxies(fmuChildFile.listFiles()));
break;
case FMUResourceUtil.FOLDER_BINARIES:
for (File fmuGrandChildFile : fmuChildFile.listFiles()) {
switch (fmuGrandChildFile.getName()) {
case FMUResourceUtil.BINARIES_WIN32:
fmuBundle.getWin32Files()
.addAll(FMUResourceUtil.createJavaFileProxies(fmuGrandChildFile.listFiles()));
break;
case FMUResourceUtil.BINARIES_WIN64:
fmuBundle.getWin64Files()
.addAll(FMUResourceUtil.createJavaFileProxies(fmuGrandChildFile.listFiles()));
break;
case FMUResourceUtil.BINARIES_LINUX32:
fmuBundle.getLinux32Files()
.addAll(FMUResourceUtil.createJavaFileProxies(fmuGrandChildFile.listFiles()));
break;
case FMUResourceUtil.BINARIES_LINUX64:
fmuBundle.getLinux64Files()
.addAll(FMUResourceUtil.createJavaFileProxies(fmuGrandChildFile.listFiles()));
break;
case FMUResourceUtil.BINARIES_DARWIN32:
fmuBundle.getDarwin32Files()
.addAll(FMUResourceUtil.createJavaFileProxies(fmuGrandChildFile.listFiles()));
break;
case FMUResourceUtil.BINARIES_DARWIN64:
fmuBundle.getDarwin64Files()
.addAll(FMUResourceUtil.createJavaFileProxies(fmuGrandChildFile.listFiles()));
break;
default:
// there should not be a file there, but we keep track
// of it as a root file with a compound path
fmuBundle.getRootFiles().add(FMUResourceUtil.createJavaFileProxy(fmuGrandChildFile,
FMUResourceUtil.FOLDER_BINARIES + "/" + fmuGrandChildFile.getName()));
break;
}
}
default:
if (! FMUResourceUtil.isAStandardFile(fmuChildFile)){
fmuBundle.getRootFiles().add(FMUResourceUtil.createJavaFileProxy(fmuChildFile));
}
break;
}
}
}
@Override
public void doSave(OutputStream outputStream, Map<?, ?> options) throws IOException {
if (getContents().get(0) instanceof FMUBundle) {
fmuBundle = (FMUBundle) getContents().get(0);
ZipOutputStream zipOputputStream = new ZipOutputStream(outputStream);
saveModelDescription(zipOputputStream);
saveBinaries(zipOputputStream);
saveResources(zipOputputStream);
saveSources(zipOputputStream);
saveDocumentation(zipOputputStream);
saveRoot(zipOputputStream);
zipOputputStream.close();
} else {
throw new IOException("The content of the FMUResource should be a FMUBundle");
}
}
private void saveModelDescription(ZipOutputStream zipOutputStream) throws IOException {
if (fmuBundle.getModelDescription() != null) {
XMLResource modelDescRes = new FmiResourceImpl(null);
FmiModelDescriptionType modelDesc = EcoreUtil.copy(fmuBundle.getModelDescription());
DocumentRoot root = FmiFactory.eINSTANCE.createDocumentRoot();
root.setFmiModelDescription(modelDesc);
modelDescRes.getContents().add(root);
ExtendedMetaData exMet = new BasicExtendedMetaData();
exMet.setQualified(FmiPackage.eINSTANCE, false);
Map<Object, Object> saveOptions = new HashMap<Object, Object>();
saveOptions.put(XMLResource.OPTION_EXTENDED_META_DATA, exMet);
saveOptions.put(XMLResource.OPTION_ENCODING, "utf-8");
StringWriter stringWriter = new StringWriter();
modelDescRes.save(stringWriter, saveOptions);
ZipEntry modelDescEntry = new ZipEntry(FMUResourceUtil.MODEL_DESCRIPTION_FILE_NAME);
zipOutputStream.putNextEntry(modelDescEntry);
zipOutputStream.write(stringWriter.getBuffer().toString().getBytes());
zipOutputStream.closeEntry();
}
}
private void saveBinaries(ZipOutputStream zipOputputStream) throws IOException {
addFiles(fmuBundle.getWin32Files(), zipOputputStream,
FMUResourceUtil.FOLDER_BINARIES + "/" + FMUResourceUtil.BINARIES_WIN32);
addFiles(fmuBundle.getWin64Files(), zipOputputStream,
FMUResourceUtil.FOLDER_BINARIES + "/" + FMUResourceUtil.BINARIES_WIN64);
addFiles(fmuBundle.getLinux32Files(), zipOputputStream,
FMUResourceUtil.FOLDER_BINARIES + "/" + FMUResourceUtil.BINARIES_LINUX32);
addFiles(fmuBundle.getLinux64Files(), zipOputputStream,
FMUResourceUtil.FOLDER_BINARIES + "/" + FMUResourceUtil.BINARIES_LINUX64);
addFiles(fmuBundle.getDarwin32Files(), zipOputputStream,
FMUResourceUtil.FOLDER_BINARIES + "/" + FMUResourceUtil.BINARIES_DARWIN32);
addFiles(fmuBundle.getDarwin64Files(), zipOputputStream,
FMUResourceUtil.FOLDER_BINARIES + "/" + FMUResourceUtil.BINARIES_DARWIN64);
}
private void saveRoot(ZipOutputStream zipOutputStream) throws IOException {
addFiles(fmuBundle.getRootFiles(), zipOutputStream, ".");
}
private void saveDocumentation(ZipOutputStream zipOutputStream) throws IOException {
addFiles(fmuBundle.getDocumentationFiles(), zipOutputStream,FMUResourceUtil.FOLDER_DOCUMENTATION );
}
private void saveResources(ZipOutputStream zipOutputStream) throws IOException {
addFiles(fmuBundle.getResourcesFiles(), zipOutputStream, FMUResourceUtil.FOLDER_RESOURCES);
}
private void saveSources(ZipOutputStream zipOutputStream) throws IOException {
addFiles(fmuBundle.getSourceFiles(), zipOutputStream, FMUResourceUtil.FOLDER_SOURCES);
}
private void addFile(AbstractFile fmuFile, ZipOutputStream zipOutputStream, String fmuFolder) throws IOException {
if (fmuFile instanceof JavaFileProxy && ((JavaFileProxy) fmuFile).getFile() != null
&& ((JavaFileProxy) fmuFile).getFile().exists()) {
addEntry(((JavaFileProxy) fmuFile).getFile(), zipOutputStream, fmuFolder, fmuFile.getName());
} else if (fmuFile instanceof FolderToCreateInFMU) {
FolderToCreateInFMU folderToCreate = (FolderToCreateInFMU) fmuFile;
if (folderToCreate.getChildren().isEmpty()) {
createEmptyDir(zipOutputStream, fmuFolder + "/" + folderToCreate.getName());
} else {
for (AbstractFile childFile : folderToCreate.getChildren()) {
addFile(childFile, zipOutputStream, fmuFolder + "/" + folderToCreate.getName());
}
}
} else if (fmuFile instanceof ArchiveToUnzipInFMU) {
unzipArchiveFile((ArchiveToUnzipInFMU) fmuFile, zipOutputStream, fmuFolder);
}
}
private void addFiles(List<AbstractFile> fmuFiles, ZipOutputStream zipOutputStream, String fmuFolder)
throws IOException {
for (AbstractFile fmuFile : fmuFiles) {
addFile(fmuFile, zipOutputStream, fmuFolder);
}
}
private void unzipArchiveFile(ArchiveToUnzipInFMU archiveToAdd, ZipOutputStream zipOutputStream, String fmuFolder)
throws IOException {
if (archiveToAdd.getArchiveFile() != null && archiveToAdd.getArchiveFile().exists()) {
String rootName = fmuFolder;
try (ZipInputStream zipIn = new ZipInputStream(new FileInputStream(archiveToAdd.getArchiveFile()));) {
if (archiveToAdd.getName() != null) {
rootName = fmuFolder +"/"+ archiveToAdd.getName();
}
ZipEntry entryToCopy;
while ((entryToCopy = zipIn.getNextEntry()) != null) {
ZipEntry newEntry = new ZipEntry(rootName + "/" + entryToCopy.getName());
zipOutputStream.putNextEntry(newEntry);
byte[] buffer = new byte[1024];
int len;
while ((len = zipIn.read(buffer)) > 0) {
zipOutputStream.write(buffer, 0, len);
}
zipOutputStream.closeEntry();
}
}
;
}
}
private void createEmptyDir(ZipOutputStream zipOutputStream, String entryName) throws IOException {
ZipEntry emptyDirEntry = new ZipEntry(entryName + "/");
zipOutputStream.putNextEntry(emptyDirEntry);
zipOutputStream.closeEntry();
}
private void addEntry(File file, ZipOutputStream zipOutputStream, String fmuFolder, String entryName)
throws IOException {
String name = entryName != null ? entryName : file.getName();
if (file.isDirectory()) {
if (file.listFiles().length == 0) {
createEmptyDir(zipOutputStream, fmuFolder + "/" + name);
}
for (File child : file.listFiles()) {
addEntry(child, zipOutputStream, fmuFolder + "/" + name, null);
}
} else {
ZipEntry fileEntry = new ZipEntry(fmuFolder + "/" + name);
try (FileInputStream in = new FileInputStream(file)) {
zipOutputStream.putNextEntry(fileEntry);
byte[] buffer = new byte[1024];
int len;
while ((len = in.read(buffer)) > 0) {
zipOutputStream.write(buffer, 0, len);
}
zipOutputStream.closeEntry();
}
}
}
@Override
protected void doUnload() {
super.doUnload();
if (fmuParser != null) {
fmuParser.clean();
fmuParser = null;
}
}
}