1 package org.simantics.fmil.core;
4 import java.io.IOException;
5 import java.io.RandomAccessFile;
7 import java.nio.channels.FileChannel;
8 import java.nio.channels.FileLock;
9 import java.nio.file.Files;
10 import java.nio.file.Paths;
11 import java.util.ArrayList;
12 import java.util.Arrays;
13 import java.util.HashSet;
14 import java.util.List;
16 import java.util.UUID;
18 import org.eclipse.core.runtime.FileLocator;
19 import org.eclipse.core.runtime.Path;
20 import org.eclipse.core.runtime.Platform;
21 import org.osgi.framework.Bundle;
22 import org.simantics.fmil.core.ExecEnvironment.OSType;
23 import org.simantics.utils.FileUtils;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
27 import gnu.trove.list.array.TIntArrayList;
28 import gnu.trove.map.hash.TObjectIntHashMap;
33 private static final Logger LOGGER = LoggerFactory.getLogger(FMIL.class);
38 private static int OK = 0;
39 private static int ERROR = 1;
40 private static String UNSATISFIED_LINK = "Method not found. DLL might not be loaded properly.";
41 public static final String TEMP_FMU_DIRECTORY_NAME = "fmil";
42 public static String TEMP_FMU_COMMON_DIRECTORY;
43 public static String LOCK_FILE_NAME = "fmil.lock";
45 public static Object syncObject = new Object();
48 * Static: load native libraries required for the FMU simulation to work.
52 File[] libraries = new File[2];
54 ExecEnvironment env = ExecEnvironment.calculate();
57 URL sharedFMILIBUrl = null;
58 URL simulatorFMIUrl = null;
59 Bundle b = Platform.getBundle("org.simantics.fmil.core");
61 if (env.os == OSType.WINDOWS) {
62 sharedFMILIBUrl = FileLocator.find(b, new Path("libraries/fmilib_shared.dll"), null);
63 simulatorFMIUrl = FileLocator.find(b, new Path("libraries/FMUSimulator.dll"), null);
64 } else if(env.os == OSType.LINUX) {
65 sharedFMILIBUrl = FileLocator.find(b, new Path("libraries/libfmilib_shared.so"), null);
66 simulatorFMIUrl = FileLocator.find(b, new Path("libraries/libFMUSimulator.so"), null);
69 libraries[0] = new File(FileLocator.toFileURL(sharedFMILIBUrl).getPath());
70 libraries[1] = new File(FileLocator.toFileURL(simulatorFMIUrl).getPath());
71 } catch (Exception e) {
72 LOGGER.error("Failed to resolve native FMU simulation library for execution environment {}.{}", env.os, env.arch, e);
75 for(File library : libraries) {
77 System.err.println("FMU library not loaded. FMU simulation not working.");
79 } else if(!library.isFile()) {
80 System.err.println(library.getAbsolutePath() + " not found");
83 System.load(library.getAbsolutePath());
84 } catch (Throwable t) {
85 System.err.println(t.getMessage());
92 * Static: initialize fmu temp folder from current working directory
95 TEMP_FMU_COMMON_DIRECTORY = Paths.get(".").toAbsolutePath().normalize().toString();
98 public static void setTempFMUCommonDir(File dir) {
99 TEMP_FMU_COMMON_DIRECTORY = dir.getAbsolutePath();
102 private String fmuDir;
105 public String TEMP_FOLDER_1;
106 public String TEMP_FOLDER_2;
107 public String TEMP_FMU_DIRECTORY;
108 private String dirName;
110 private String[] variableNames;
111 private String[] variableDescriptions;
112 private String[] variableDeclaredTypes;
113 private int[] variableReferences;
114 private int[] variableTypes;
115 private int[] variableCausalities;
116 private int[] variableVariabilities;
118 private String[] declaredTypes;
119 private String[] declaredTypeDescriptions;
120 private String[] declaredTypeQuantities;
121 private String[] declaredTypeUnits;
123 private TObjectIntHashMap<String> variableMap = new TObjectIntHashMap<String>();
125 private Set<String> subscriptionSet = new HashSet<String>();
126 private TIntArrayList subscription = new TIntArrayList();
127 private ArrayList<String> subscribedNames = new ArrayList<String>();
129 public List<String> getSubscribedNames() {
130 return subscribedNames;
133 public boolean subscribe(String name) throws FMILException {
134 synchronized(syncObject) {
136 int vr = variableMap.get(name);
137 if(vr == 0) return false;
138 if(!subscriptionSet.add(name)) return false;
139 subscribedNames.add(name);
140 subscription.add(vr);
141 subscribe(new int[] { vr });
147 // Create a directory for this control
148 File tempDir = new File(TEMP_FMU_COMMON_DIRECTORY, UUID.randomUUID().toString());
150 TEMP_FMU_DIRECTORY = tempDir.getAbsolutePath();
152 // Create two directories inside the temp directory for this control
153 dirName = UUID.randomUUID().toString();
154 File fmuDir = new File(TEMP_FMU_DIRECTORY, dirName);
157 TEMP_FOLDER_1 = fmuDir.toString();
158 TEMP_FOLDER_2 = fmuDir.toString() + "_2";
160 // Lock fmu directory in temp directory
164 public int getModelIDNew() {
168 public String getModelID() {
172 public String getFmuDir() {
177 * Load fmu from a given file path. Releases the (possible) previously
180 * @param path absolute file path for fmu file
181 * @throws FMILException
183 private int fmuN = 0;
184 private boolean fmuLoaded = false;
185 public void loadFMUFile(String path) throws FMILException {
187 synchronized(syncObject) {
190 fmuDir = TEMP_FOLDER_1;
193 fmuDir = TEMP_FOLDER_2;
197 java.nio.file.Path tempDir = Paths.get(fmuDir);
198 if(Files.exists(tempDir) && Files.isDirectory(tempDir)) {
200 FileUtils.emptyDirectory(tempDir);
201 } catch (IOException e) {
202 throw new FMILException("Could not delete existing files from temp folder for fmu " + path, e);
206 Files.createDirectory(tempDir);
207 } catch (IOException e) {
208 throw new FMILException("Could not create temp folder for fmu " + path, e);
213 String tmpPath = tempDir.toString();
214 if(!tmpPath.endsWith("\\") && !tmpPath.endsWith("/"))
215 tmpPath = tmpPath + "/";
216 id = loadFMUFile_(path, tmpPath);
219 getAllVariableReferences();
221 for(int i=0;i<variableNames.length;i++) {
222 variableMap.put(variableNames[i], variableReferences[i]);
226 } catch (UnsatisfiedLinkError err) {
227 throw new FMILException(UNSATISFIED_LINK, err);
228 } catch (Exception e) {
229 LOGGER.error(e.getMessage());
230 throw new FMILException(e.getMessage());
235 private native int loadFMUFile_(String path, String toDir);
238 * Set a step length for simulation
240 * @param step Step length for simulation
241 * @throws FMILException
243 public void setStepLength(double step) throws FMILException {
244 synchronized(syncObject) {
247 int ret = setStepLength_(getModelIDNew(), step);
249 LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
251 } catch (UnsatisfiedLinkError err) {
252 throw new FMILException(UNSATISFIED_LINK);
253 } catch (Exception e) {
254 throw new FMILException(e.getMessage());
259 private native int setStepLength_(int id, double step);
262 * Instantiates a simulation.
264 * Make sure that an FMU is loaded first.
265 * @throws FMILException
267 public void instantiateSimulation() throws FMILException {
268 synchronized(syncObject) {
272 int ret = instantiateSimulation_(getModelIDNew());
274 LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
276 } catch (FMILException e) {
278 } catch (UnsatisfiedLinkError err) {
279 throw new FMILException(UNSATISFIED_LINK);
280 } catch (Exception e) {
281 throw new FMILException(e.getMessage());
286 private native int instantiateSimulation_(int id) throws FMILException;
290 * Initializes a simulation.
292 * Make sure that simulation is instantiated first!
293 * @throws FMILException
295 public void initializeSimulation() throws FMILException {
296 synchronized(syncObject) {
300 int ret = initializeSimulation_(getModelIDNew());
302 LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
304 } catch (FMILException e) {
306 } catch (UnsatisfiedLinkError err) {
307 throw new FMILException(UNSATISFIED_LINK);
308 } catch (Exception e) {
309 throw new FMILException(e.getMessage());
314 private native int initializeSimulation_(int id) throws FMILException;
317 * Subscribe a set of variables from a loaded simulation.
319 * Make sure that an FMU is loaded first.
320 * @param variables Array of variables
321 * @throws FMILException
323 public void subscribe(int[] variables) throws FMILException {
324 synchronized(syncObject) {
328 int ret = subscribe_(getModelIDNew(), variables);
330 LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
332 } catch (UnsatisfiedLinkError err) {
333 throw new FMILException(UNSATISFIED_LINK);
334 } catch (Exception e) {
335 throw new FMILException(e.getMessage());
340 private native int subscribe_(int id, int[] variables);
343 * Set a new (Real, double) value for a variable. If the variable is a
344 * parameter, the change is effective immediately.
346 * @param name Variable
347 * @param value New (Real, double) value
348 * @throws FMILException
350 public void setRealValue(String name, double value) throws FMILException {
352 synchronized(syncObject) {
356 int ret = setRealValue_(getModelIDNew(), variableMap.get(name), value);
358 LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
360 } catch (FMILException e) {
362 } catch (UnsatisfiedLinkError err) {
363 throw new FMILException(UNSATISFIED_LINK);
364 } catch (Exception e) {
365 throw new FMILException(e.getMessage());
372 public void setRealValue(int variableReference, double value) throws FMILException {
374 synchronized(syncObject) {
378 int ret = setRealValue_(getModelIDNew(), variableReference, value);
380 LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
382 } catch (FMILException e) {
384 } catch (UnsatisfiedLinkError err) {
385 throw new FMILException(UNSATISFIED_LINK);
386 } catch (Exception e) {
387 throw new FMILException(e.getMessage());
394 private native int setRealValue_(int id, int variableReference, double value) throws FMILException;
397 // * Set a new (integer) value for a variable. If the variable is a
398 // * parameter, the change is effective immediately.
400 // * @param name Variable
401 // * @param value New (integer) value
402 // * @throws FMILException
404 // public void setIntegerValue(String name, int value) throws FMILException {
405 // synchronized(syncObject) {
409 // int ret = setIntegerValue_(getModelID(), name, value);
411 // throw new FMILException(getLastErrorMessage());
413 // } catch (UnsatisfiedLinkError err) {
414 // throw new FMILException(UNSATISFIED_LINK);
415 // } catch (Exception e) {
416 // throw new FMILException(e.getMessage());
420 // private native int setIntegerValue_(String id, String name, int value);
423 // * Set a new (boolean) value for a variable. If the variable is a
424 // * parameter, the change is effective immediately.
426 // * @param name Variable
427 // * @param value New (boolean) value
428 // * @throws FMILException
430 // public void setBooleanValue(String name, boolean value) throws FMILException {
431 // synchronized(syncObject) {
435 // int ret = setBooleanValue_(getModelID(), name, value);
437 // throw new FMILException(getLastErrorMessage());
439 // } catch (UnsatisfiedLinkError err) {
440 // throw new FMILException(UNSATISFIED_LINK);
441 // } catch (Exception e) {
442 // throw new FMILException(e.getMessage());
446 // private native int setBooleanValue_(String id, String name, boolean value);
448 // public void setTime(double time) throws FMILException {
449 // synchronized(syncObject) {
453 // int ret = setTime_(getModelID(), time);
455 // throw new FMILException(getLastErrorMessage());
457 // } catch (UnsatisfiedLinkError err) {
458 // throw new FMILException(UNSATISFIED_LINK);
459 // } catch (Exception e) {
460 // throw new FMILException(e.getMessage());
464 // private native int setTime_(String id, double time);
467 * Simulate one step forward. The step length can be set with
470 * @throws FMILException
472 public void simulateStep() throws FMILException {
473 synchronized(syncObject) {
477 int ret = simulateStep_(getModelIDNew());
479 LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
481 } catch (FMILException e) {
483 } catch (UnsatisfiedLinkError err) {
484 throw new FMILException(UNSATISFIED_LINK);
485 } catch (Exception e) {
486 throw new FMILException(e.getMessage());
490 private native int simulateStep_(int id) throws FMILException;
493 * Get an array containing the current values for subscribed variables. The
494 * values are in the same order as in the subscription.
496 * @param results An array the size of subscribed results
499 public double[] getSubscribedResults() throws FMILException {
500 synchronized(syncObject) {
504 double[] results = new double[subscription.size()];
505 Arrays.fill(results, Double.NaN);
507 return getSubscribedResults_(getModelIDNew(), results);
508 } catch (UnsatisfiedLinkError err) {
509 throw new FMILException(UNSATISFIED_LINK);
510 } catch (Exception e) {
511 throw new FMILException(e.getMessage());
516 private native double[] getSubscribedResults_(int id, double[] results);
520 * Unload FMU and the dll:s that it requires.
522 * To be called after all FMU simulations are ended.
523 * If the fmu is loaded again / changed, call to loadFMUFile is sufficient. loadFMUFile
524 * releases the previous fmu.dll
526 * @throws FMILException
528 public void unloadFMU() throws FMILException {
529 synchronized(syncObject) {
533 unlockFMUDirectory();
535 int ret = unloadFMU_(getModelIDNew());
537 LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
540 removeFMUDirectoryContents();
542 } catch (FMILException e) {
544 } catch (UnsatisfiedLinkError err) {
545 throw new FMILException(UNSATISFIED_LINK);
546 } catch (Exception e) {
547 throw new FMILException(e.getMessage());
551 private native int unloadFMU_(int id) throws FMILException;
554 // * Checks if fmu has been initialized
555 // * @return current simulation time
557 // public boolean isInitialized() throws FMILException {
558 // synchronized(syncObject) {
560 // return isInitialized_(getModelID());
561 // } catch (UnsatisfiedLinkError err) {
562 // throw new FMILException(UNSATISFIED_LINK);
563 // } catch (Exception e) {
564 // throw new FMILException(e.getMessage());
569 // private native boolean isInitialized_(String id);
572 * Get the current simulation time
573 * @return current simulation time
575 public double getTime() throws FMILException {
576 synchronized(syncObject) {
580 return getTime_(getModelIDNew());
582 } catch (UnsatisfiedLinkError err) {
583 throw new FMILException(UNSATISFIED_LINK);
584 } catch (Exception e) {
585 throw new FMILException(e.getMessage());
590 private native double getTime_(int id);
593 * Get all variables in a loaded model
594 * @return all variables in a loaded model
596 public String[] getAllVariables() throws FMILException {
597 synchronized(syncObject) {
601 if(variableNames == null) {
602 variableNames = getAllVariables_(getModelIDNew());
604 return variableNames;
606 } catch (UnsatisfiedLinkError err) {
607 throw new FMILException(UNSATISFIED_LINK);
608 } catch (Exception e) {
609 throw new FMILException(e.getMessage());
614 private native String[] getAllVariables_(int id);
616 public String[] getAllVariableDescriptions() throws FMILException {
617 synchronized(syncObject) {
621 if(variableDescriptions == null) {
622 variableDescriptions = getAllVariableDescriptions_(getModelIDNew());
624 return variableDescriptions;
626 } catch (UnsatisfiedLinkError err) {
627 throw new FMILException(UNSATISFIED_LINK);
628 } catch (Exception e) {
629 throw new FMILException(e.getMessage());
634 private native String[] getAllVariableDescriptions_(int id);
636 public String[] getAllVariableDeclaredTypes() throws FMILException {
637 synchronized(syncObject) {
641 if(variableDeclaredTypes == null) {
642 variableDeclaredTypes = getAllVariableDeclaredTypes_(getModelIDNew());
644 return variableDeclaredTypes;
646 } catch (UnsatisfiedLinkError err) {
647 throw new FMILException(UNSATISFIED_LINK);
648 } catch (Exception e) {
649 throw new FMILException(e.getMessage());
654 private native String[] getAllVariableDeclaredTypes_(int id);
656 public int[] getAllVariableReferences() throws FMILException {
657 synchronized(syncObject) {
661 if(variableReferences == null) {
662 variableReferences = getAllVariableReferences_(getModelIDNew(), new int[variableNames.length]);
664 return variableReferences;
666 } catch (UnsatisfiedLinkError err) {
667 throw new FMILException(UNSATISFIED_LINK);
668 } catch (Exception e) {
669 throw new FMILException(e.getMessage());
674 private native int[] getAllVariableReferences_(int id, int[] array);
676 public int[] getAllVariableTypes() throws FMILException {
677 synchronized(syncObject) {
681 if(variableTypes == null) {
682 variableTypes = getAllVariableTypes_(getModelIDNew(), new int[variableNames.length]);
684 return variableTypes;
686 } catch (UnsatisfiedLinkError err) {
687 throw new FMILException(UNSATISFIED_LINK);
688 } catch (Exception e) {
689 throw new FMILException(e.getMessage());
694 private native int[] getAllVariableTypes_(int id, int[] array);
696 public int[] getAllVariableCausalities() throws FMILException {
697 synchronized(syncObject) {
701 if(variableCausalities == null) {
702 variableCausalities = getAllVariableCausalities_(getModelIDNew(), new int[variableNames.length]);
704 return variableCausalities;
706 } catch (UnsatisfiedLinkError err) {
707 throw new FMILException(UNSATISFIED_LINK);
708 } catch (Exception e) {
709 throw new FMILException(e.getMessage());
714 private native int[] getAllVariableCausalities_(int id, int[] array);
716 public int[] getAllVariableVariabilities() throws FMILException {
717 synchronized(syncObject) {
721 if(variableVariabilities == null) {
722 variableVariabilities = getAllVariableVariabilities_(getModelIDNew(), new int[variableNames.length]);
724 return variableVariabilities;
726 } catch (UnsatisfiedLinkError err) {
727 throw new FMILException(UNSATISFIED_LINK);
728 } catch (Exception e) {
729 throw new FMILException(e.getMessage());
734 private native int[] getAllVariableVariabilities_(int id, int[] array);
737 * Get all variables in a loaded model
738 * @return all variables in a loaded model
740 public String[] getAllDeclaredTypes() throws FMILException {
741 synchronized(syncObject) {
745 if(declaredTypes == null) {
746 declaredTypes = getAllDeclaredTypes_(getModelIDNew());
748 return declaredTypes;
750 } catch (UnsatisfiedLinkError err) {
751 throw new FMILException(UNSATISFIED_LINK);
752 } catch (Exception e) {
753 throw new FMILException(e.getMessage());
758 private native String[] getAllDeclaredTypes_(int id);
760 public String[] getAllDeclaredTypeDescriptions() throws FMILException {
761 synchronized(syncObject) {
765 if(declaredTypeDescriptions == null) {
766 declaredTypeDescriptions = getAllDeclaredTypeDescriptions_(getModelIDNew());
768 return declaredTypeDescriptions;
770 } catch (UnsatisfiedLinkError err) {
771 throw new FMILException(UNSATISFIED_LINK);
772 } catch (Exception e) {
773 throw new FMILException(e.getMessage());
778 private native String[] getAllDeclaredTypeDescriptions_(int id);
780 public String[] getAllDeclaredTypeQuantities() throws FMILException {
781 synchronized(syncObject) {
785 if(declaredTypeQuantities == null) {
786 declaredTypeQuantities = getAllDeclaredTypeQuantities_(getModelIDNew());
788 return declaredTypeQuantities;
790 } catch (UnsatisfiedLinkError err) {
791 throw new FMILException(UNSATISFIED_LINK);
792 } catch (Exception e) {
793 throw new FMILException(e.getMessage());
798 private native String[] getAllDeclaredTypeQuantities_(int id);
800 public String[] getAllDeclaredTypeUnits() throws FMILException {
801 synchronized(syncObject) {
805 if(declaredTypeUnits == null) {
806 declaredTypeUnits = getAllDeclaredTypeUnits_(getModelIDNew());
808 return declaredTypeUnits;
810 } catch (UnsatisfiedLinkError err) {
811 throw new FMILException(UNSATISFIED_LINK);
812 } catch (Exception e) {
813 throw new FMILException(e.getMessage());
818 private native String[] getAllDeclaredTypeUnits_(int id);
823 // * Get all variables from model that match the filter (and time variable)
825 // * @param regexp Regular expression filter
826 // * @return An array of variable names that match regexp filter (and time-variable)
827 // * @throws FMILException
829 // public String[] filterVariables(String regexp) throws FMILException {
830 // synchronized(syncObject) {
833 // return filterVariables_(getModelID(), regexp + "|time");
835 // } catch (UnsatisfiedLinkError err) {
836 // throw new FMILException(UNSATISFIED_LINK);
837 // } catch (Exception e) {
838 // throw new FMILException(e.getMessage());
843 // private native String[] filterVariables_(String id, String regexp);
846 // * Get the last error message
847 // * @return Last error message
849 // public String getLastErrorMessage() throws FMILException {
850 // synchronized(syncObject) {
855 // //return getLastErrorMessage_(getModelID());
857 // } catch (UnsatisfiedLinkError err) {
858 // throw new FMILException(UNSATISFIED_LINK);
859 // } catch (Exception e) {
860 // throw new FMILException(e.getMessage());
865 // private native String getLastErrorMessage_(String id);
868 * Get a real (double) value for variable
869 * @param name Name of the variable
871 * @throws FMILException
873 public double getRealValue(String name) throws FMILException {
874 synchronized(syncObject) {
877 // TODO: printtaa id ja name, jotta saadaan virheessä kiinni
878 double result = getRealValue_(getModelIDNew(), variableMap.get(name));
879 System.err.println("getRealValue " + name + " = " + result);
881 } catch (UnsatisfiedLinkError err) {
882 throw new FMILException(UNSATISFIED_LINK);
883 } catch (Exception e) {
884 throw new FMILException(e.getMessage());
889 private native double getRealValue_(int id, int variableReference);
892 // * Get a string value for variable
893 // * @param name Name of the variable
895 // * @throws FMILException
897 // public String getStringValue(String name) throws FMILException {
898 // synchronized(syncObject) {
901 // return getStringValue_(getModelID(), name);
902 // } catch (UnsatisfiedLinkError err) {
903 // throw new FMILException(UNSATISFIED_LINK);
904 // } catch (Exception e) {
905 // throw new FMILException(e.getMessage());
910 // private native String getStringValue_(String id, String name);
913 // * Get an integer value for variable
914 // * @param name Name of the variable
916 // * @throws FMILException
918 // public int getIntegerValue(String name) throws FMILException {
919 // synchronized(syncObject) {
922 // return getIntegerValue_(getModelID(), name);
923 // } catch (UnsatisfiedLinkError err) {
924 // throw new FMILException(UNSATISFIED_LINK);
925 // } catch (Exception e) {
926 // throw new FMILException(e.getMessage());
931 // private native int getIntegerValue_(String id, String name);
934 // * Get a real (double) value for variable
935 // * @param name Name of the variable
937 // * @throws FMILException
939 // public boolean getBooleanValue(String name) throws FMILException {
940 // synchronized(syncObject) {
943 // return getBooleanValue_(getModelID(), name);
944 // } catch (UnsatisfiedLinkError err) {
945 // throw new FMILException(UNSATISFIED_LINK);
946 // } catch (Exception e) {
947 // throw new FMILException(e.getMessage());
952 // private native boolean getBooleanValue_(String id, String name);
954 private FileChannel channel;
955 private FileLock lock;
957 @SuppressWarnings("resource")
958 private boolean lockFMUDirectory() {
961 // Get a file channel for the lock file
962 File lockFile = new File(TEMP_FMU_DIRECTORY, LOCK_FILE_NAME);
963 if(!lockFile.isFile())
964 lockFile.createNewFile();
966 channel = new RandomAccessFile(lockFile, "rw").getChannel();
968 // Use the file channel to create a lock on the file.
969 // This method blocks until it can retrieve the lock.
970 lock = channel.lock();
972 // // Try acquiring the lock without blocking. This method returns
973 // // null or throws an exception if the file is already locked.
975 // lock = channel.tryLock();
976 // } catch (OverlappingFileLockException e) {
977 // // File is already locked in this thread or virtual machine
979 } catch (IOException e) {
986 private boolean unlockFMUDirectory() {
995 } catch (IOException e) {
1001 private boolean removeFMUDirectoryContents() {
1004 File tempDir = new File(TEMP_FMU_DIRECTORY);
1005 FileUtils.deleteAll(tempDir);
1007 } catch (IOException e) {
1014 protected void finalize() throws Throwable {
1017 } catch (Throwable t) {
1018 LOGGER.error("Could not unload native FMU!", t);