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 if (!Files.exists(Paths.get(path)))
188 throw new FMILException("File " + path + " does not exist");
189 if (!Files.isRegularFile(Paths.get(path)))
190 throw new FMILException("Path " + path + " is not a file");
192 synchronized(syncObject) {
195 fmuDir = TEMP_FOLDER_1;
198 fmuDir = TEMP_FOLDER_2;
202 java.nio.file.Path tempDir = Paths.get(fmuDir);
203 if(Files.exists(tempDir) && Files.isDirectory(tempDir)) {
205 FileUtils.emptyDirectory(tempDir);
206 } catch (IOException e) {
207 throw new FMILException("Could not delete existing files from temp folder for fmu " + path, e);
211 Files.createDirectory(tempDir);
212 } catch (IOException e) {
213 throw new FMILException("Could not create temp folder for fmu " + path, e);
218 String tmpPath = tempDir.toString();
219 if(!tmpPath.endsWith("\\") && !tmpPath.endsWith("/"))
220 tmpPath = tmpPath + "/";
221 id = loadFMUFile_(path, tmpPath);
224 getAllVariableReferences();
226 for(int i=0;i<variableNames.length;i++) {
227 variableMap.put(variableNames[i], variableReferences[i]);
231 } catch (UnsatisfiedLinkError err) {
232 throw new FMILException(UNSATISFIED_LINK, err);
233 } catch (Exception e) {
234 LOGGER.error(e.getMessage());
235 throw new FMILException(e.getMessage());
240 private native int loadFMUFile_(String path, String toDir) throws FMILException;
243 * Set a step length for simulation
245 * @param step Step length for simulation
246 * @throws FMILException
248 public void setStepLength(double step) throws FMILException {
249 synchronized(syncObject) {
252 int ret = setStepLength_(getModelIDNew(), step);
254 LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
256 } catch (UnsatisfiedLinkError err) {
257 throw new FMILException(UNSATISFIED_LINK);
258 } catch (Exception e) {
259 throw new FMILException(e.getMessage());
264 private native int setStepLength_(int id, double step);
267 * Instantiates a simulation.
269 * Make sure that an FMU is loaded first.
270 * @throws FMILException
272 public void instantiateSimulation() throws FMILException {
273 synchronized(syncObject) {
277 int ret = instantiateSimulation_(getModelIDNew());
279 LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
281 } catch (FMILException e) {
283 } catch (UnsatisfiedLinkError err) {
284 throw new FMILException(UNSATISFIED_LINK);
285 } catch (Exception e) {
286 throw new FMILException(e.getMessage());
291 private native int instantiateSimulation_(int id) throws FMILException;
295 * Initializes a simulation.
297 * Make sure that simulation is instantiated first!
298 * @throws FMILException
300 public void initializeSimulation() throws FMILException {
301 synchronized(syncObject) {
305 int ret = initializeSimulation_(getModelIDNew());
307 LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
309 } catch (FMILException e) {
311 } catch (UnsatisfiedLinkError err) {
312 throw new FMILException(UNSATISFIED_LINK);
313 } catch (Exception e) {
314 throw new FMILException(e.getMessage());
319 private native int initializeSimulation_(int id) throws FMILException;
322 * Subscribe a set of variables from a loaded simulation.
324 * Make sure that an FMU is loaded first.
325 * @param variables Array of variables
326 * @throws FMILException
328 public void subscribe(int[] variables) throws FMILException {
329 synchronized(syncObject) {
333 int ret = subscribe_(getModelIDNew(), variables);
335 LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
337 } catch (UnsatisfiedLinkError err) {
338 throw new FMILException(UNSATISFIED_LINK);
339 } catch (Exception e) {
340 throw new FMILException(e.getMessage());
345 private native int subscribe_(int id, int[] variables);
348 * Set a new (Real, double) value for a variable. If the variable is a
349 * parameter, the change is effective immediately.
351 * @param name Variable
352 * @param value New (Real, double) value
353 * @throws FMILException
355 public void setRealValue(String name, double value) throws FMILException {
357 synchronized(syncObject) {
361 int ret = setRealValue_(getModelIDNew(), variableMap.get(name), value);
363 LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
365 } catch (FMILException e) {
367 } catch (UnsatisfiedLinkError err) {
368 throw new FMILException(UNSATISFIED_LINK);
369 } catch (Exception e) {
370 throw new FMILException(e.getMessage());
377 public void setRealValue(int variableReference, double value) throws FMILException {
379 synchronized(syncObject) {
383 int ret = setRealValue_(getModelIDNew(), variableReference, value);
385 LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
387 } catch (FMILException e) {
389 } catch (UnsatisfiedLinkError err) {
390 throw new FMILException(UNSATISFIED_LINK);
391 } catch (Exception e) {
392 throw new FMILException(e.getMessage());
399 private native int setRealValue_(int id, int variableReference, double value) throws FMILException;
402 // * Set a new (integer) value for a variable. If the variable is a
403 // * parameter, the change is effective immediately.
405 // * @param name Variable
406 // * @param value New (integer) value
407 // * @throws FMILException
409 // public void setIntegerValue(String name, int value) throws FMILException {
410 // synchronized(syncObject) {
414 // int ret = setIntegerValue_(getModelID(), name, value);
416 // throw new FMILException(getLastErrorMessage());
418 // } catch (UnsatisfiedLinkError err) {
419 // throw new FMILException(UNSATISFIED_LINK);
420 // } catch (Exception e) {
421 // throw new FMILException(e.getMessage());
425 // private native int setIntegerValue_(String id, String name, int value);
428 // * Set a new (boolean) value for a variable. If the variable is a
429 // * parameter, the change is effective immediately.
431 // * @param name Variable
432 // * @param value New (boolean) value
433 // * @throws FMILException
435 // public void setBooleanValue(String name, boolean value) throws FMILException {
436 // synchronized(syncObject) {
440 // int ret = setBooleanValue_(getModelID(), name, value);
442 // throw new FMILException(getLastErrorMessage());
444 // } catch (UnsatisfiedLinkError err) {
445 // throw new FMILException(UNSATISFIED_LINK);
446 // } catch (Exception e) {
447 // throw new FMILException(e.getMessage());
451 // private native int setBooleanValue_(String id, String name, boolean value);
453 // public void setTime(double time) throws FMILException {
454 // synchronized(syncObject) {
458 // int ret = setTime_(getModelID(), time);
460 // throw new FMILException(getLastErrorMessage());
462 // } catch (UnsatisfiedLinkError err) {
463 // throw new FMILException(UNSATISFIED_LINK);
464 // } catch (Exception e) {
465 // throw new FMILException(e.getMessage());
469 // private native int setTime_(String id, double time);
472 * Simulate one step forward. The step length can be set with
475 * @throws FMILException
477 public void simulateStep() throws FMILException {
478 synchronized(syncObject) {
482 int ret = simulateStep_(getModelIDNew());
484 LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
486 } catch (FMILException e) {
488 } catch (UnsatisfiedLinkError err) {
489 throw new FMILException(UNSATISFIED_LINK);
490 } catch (Exception e) {
491 throw new FMILException(e.getMessage());
495 private native int simulateStep_(int id) throws FMILException;
498 * Get an array containing the current values for subscribed variables. The
499 * values are in the same order as in the subscription.
501 * @param results An array the size of subscribed results
504 public double[] getSubscribedResults() throws FMILException {
505 synchronized(syncObject) {
509 double[] results = new double[subscription.size()];
510 Arrays.fill(results, Double.NaN);
512 return getSubscribedResults_(getModelIDNew(), results);
513 } catch (UnsatisfiedLinkError err) {
514 throw new FMILException(UNSATISFIED_LINK);
515 } catch (Exception e) {
516 throw new FMILException(e.getMessage());
521 private native double[] getSubscribedResults_(int id, double[] results);
525 * Unload FMU and the dll:s that it requires.
527 * To be called after all FMU simulations are ended.
528 * If the fmu is loaded again / changed, call to loadFMUFile is sufficient. loadFMUFile
529 * releases the previous fmu.dll
531 * @throws FMILException
533 public void unloadFMU() throws FMILException {
534 synchronized(syncObject) {
538 unlockFMUDirectory();
540 int ret = unloadFMU_(getModelIDNew());
542 LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
545 removeFMUDirectoryContents();
547 } catch (FMILException e) {
549 } catch (UnsatisfiedLinkError err) {
550 throw new FMILException(UNSATISFIED_LINK);
551 } catch (Exception e) {
552 throw new FMILException(e.getMessage());
556 private native int unloadFMU_(int id) throws FMILException;
559 // * Checks if fmu has been initialized
560 // * @return current simulation time
562 // public boolean isInitialized() throws FMILException {
563 // synchronized(syncObject) {
565 // return isInitialized_(getModelID());
566 // } catch (UnsatisfiedLinkError err) {
567 // throw new FMILException(UNSATISFIED_LINK);
568 // } catch (Exception e) {
569 // throw new FMILException(e.getMessage());
574 // private native boolean isInitialized_(String id);
577 * Get the current simulation time
578 * @return current simulation time
580 public double getTime() throws FMILException {
581 synchronized(syncObject) {
585 return getTime_(getModelIDNew());
587 } catch (UnsatisfiedLinkError err) {
588 throw new FMILException(UNSATISFIED_LINK);
589 } catch (Exception e) {
590 throw new FMILException(e.getMessage());
595 private native double getTime_(int id);
598 * Get all variables in a loaded model
599 * @return all variables in a loaded model
601 public String[] getAllVariables() throws FMILException {
602 synchronized(syncObject) {
606 if(variableNames == null) {
607 variableNames = getAllVariables_(getModelIDNew());
609 return variableNames;
611 } catch (UnsatisfiedLinkError err) {
612 throw new FMILException(UNSATISFIED_LINK);
613 } catch (Exception e) {
614 throw new FMILException(e.getMessage());
619 private native String[] getAllVariables_(int id);
621 public String[] getAllVariableDescriptions() throws FMILException {
622 synchronized(syncObject) {
626 if(variableDescriptions == null) {
627 variableDescriptions = getAllVariableDescriptions_(getModelIDNew());
629 return variableDescriptions;
631 } catch (UnsatisfiedLinkError err) {
632 throw new FMILException(UNSATISFIED_LINK);
633 } catch (Exception e) {
634 throw new FMILException(e.getMessage());
639 private native String[] getAllVariableDescriptions_(int id);
641 public String[] getAllVariableDeclaredTypes() throws FMILException {
642 synchronized(syncObject) {
646 if(variableDeclaredTypes == null) {
647 variableDeclaredTypes = getAllVariableDeclaredTypes_(getModelIDNew());
649 return variableDeclaredTypes;
651 } catch (UnsatisfiedLinkError err) {
652 throw new FMILException(UNSATISFIED_LINK);
653 } catch (Exception e) {
654 throw new FMILException(e.getMessage());
659 private native String[] getAllVariableDeclaredTypes_(int id);
661 public int[] getAllVariableReferences() throws FMILException {
662 synchronized(syncObject) {
666 if(variableReferences == null) {
667 variableReferences = getAllVariableReferences_(getModelIDNew(), new int[variableNames.length]);
669 return variableReferences;
671 } catch (UnsatisfiedLinkError err) {
672 throw new FMILException(UNSATISFIED_LINK);
673 } catch (Exception e) {
674 throw new FMILException(e.getMessage());
679 private native int[] getAllVariableReferences_(int id, int[] array);
681 public int[] getAllVariableTypes() throws FMILException {
682 synchronized(syncObject) {
686 if(variableTypes == null) {
687 variableTypes = getAllVariableTypes_(getModelIDNew(), new int[variableNames.length]);
689 return variableTypes;
691 } catch (UnsatisfiedLinkError err) {
692 throw new FMILException(UNSATISFIED_LINK);
693 } catch (Exception e) {
694 throw new FMILException(e.getMessage());
699 private native int[] getAllVariableTypes_(int id, int[] array);
701 public int[] getAllVariableCausalities() throws FMILException {
702 synchronized(syncObject) {
706 if(variableCausalities == null) {
707 variableCausalities = getAllVariableCausalities_(getModelIDNew(), new int[variableNames.length]);
709 return variableCausalities;
711 } catch (UnsatisfiedLinkError err) {
712 throw new FMILException(UNSATISFIED_LINK);
713 } catch (Exception e) {
714 throw new FMILException(e.getMessage());
719 private native int[] getAllVariableCausalities_(int id, int[] array);
721 public int[] getAllVariableVariabilities() throws FMILException {
722 synchronized(syncObject) {
726 if(variableVariabilities == null) {
727 variableVariabilities = getAllVariableVariabilities_(getModelIDNew(), new int[variableNames.length]);
729 return variableVariabilities;
731 } catch (UnsatisfiedLinkError err) {
732 throw new FMILException(UNSATISFIED_LINK);
733 } catch (Exception e) {
734 throw new FMILException(e.getMessage());
739 private native int[] getAllVariableVariabilities_(int id, int[] array);
742 * Get all variables in a loaded model
743 * @return all variables in a loaded model
745 public String[] getAllDeclaredTypes() throws FMILException {
746 synchronized(syncObject) {
750 if(declaredTypes == null) {
751 declaredTypes = getAllDeclaredTypes_(getModelIDNew());
753 return declaredTypes;
755 } catch (UnsatisfiedLinkError err) {
756 throw new FMILException(UNSATISFIED_LINK);
757 } catch (Exception e) {
758 throw new FMILException(e.getMessage());
763 private native String[] getAllDeclaredTypes_(int id);
765 public String[] getAllDeclaredTypeDescriptions() throws FMILException {
766 synchronized(syncObject) {
770 if(declaredTypeDescriptions == null) {
771 declaredTypeDescriptions = getAllDeclaredTypeDescriptions_(getModelIDNew());
773 return declaredTypeDescriptions;
775 } catch (UnsatisfiedLinkError err) {
776 throw new FMILException(UNSATISFIED_LINK);
777 } catch (Exception e) {
778 throw new FMILException(e.getMessage());
783 private native String[] getAllDeclaredTypeDescriptions_(int id);
785 public String[] getAllDeclaredTypeQuantities() throws FMILException {
786 synchronized(syncObject) {
790 if(declaredTypeQuantities == null) {
791 declaredTypeQuantities = getAllDeclaredTypeQuantities_(getModelIDNew());
793 return declaredTypeQuantities;
795 } catch (UnsatisfiedLinkError err) {
796 throw new FMILException(UNSATISFIED_LINK);
797 } catch (Exception e) {
798 throw new FMILException(e.getMessage());
803 private native String[] getAllDeclaredTypeQuantities_(int id);
805 public String[] getAllDeclaredTypeUnits() throws FMILException {
806 synchronized(syncObject) {
810 if(declaredTypeUnits == null) {
811 declaredTypeUnits = getAllDeclaredTypeUnits_(getModelIDNew());
813 return declaredTypeUnits;
815 } catch (UnsatisfiedLinkError err) {
816 throw new FMILException(UNSATISFIED_LINK);
817 } catch (Exception e) {
818 throw new FMILException(e.getMessage());
823 private native String[] getAllDeclaredTypeUnits_(int id);
828 // * Get all variables from model that match the filter (and time variable)
830 // * @param regexp Regular expression filter
831 // * @return An array of variable names that match regexp filter (and time-variable)
832 // * @throws FMILException
834 // public String[] filterVariables(String regexp) throws FMILException {
835 // synchronized(syncObject) {
838 // return filterVariables_(getModelID(), regexp + "|time");
840 // } catch (UnsatisfiedLinkError err) {
841 // throw new FMILException(UNSATISFIED_LINK);
842 // } catch (Exception e) {
843 // throw new FMILException(e.getMessage());
848 // private native String[] filterVariables_(String id, String regexp);
851 // * Get the last error message
852 // * @return Last error message
854 // public String getLastErrorMessage() throws FMILException {
855 // synchronized(syncObject) {
860 // //return getLastErrorMessage_(getModelID());
862 // } catch (UnsatisfiedLinkError err) {
863 // throw new FMILException(UNSATISFIED_LINK);
864 // } catch (Exception e) {
865 // throw new FMILException(e.getMessage());
870 // private native String getLastErrorMessage_(String id);
873 * Get a real (double) value for variable
874 * @param name Name of the variable
876 * @throws FMILException
878 public double getRealValue(String name) throws FMILException {
879 synchronized(syncObject) {
882 // TODO: printtaa id ja name, jotta saadaan virheessä kiinni
883 double result = getRealValue_(getModelIDNew(), variableMap.get(name));
884 System.err.println("getRealValue " + name + " = " + result);
886 } catch (UnsatisfiedLinkError err) {
887 throw new FMILException(UNSATISFIED_LINK);
888 } catch (Exception e) {
889 throw new FMILException(e.getMessage());
894 private native double getRealValue_(int id, int variableReference);
897 // * Get a string value for variable
898 // * @param name Name of the variable
900 // * @throws FMILException
902 // public String getStringValue(String name) throws FMILException {
903 // synchronized(syncObject) {
906 // return getStringValue_(getModelID(), name);
907 // } catch (UnsatisfiedLinkError err) {
908 // throw new FMILException(UNSATISFIED_LINK);
909 // } catch (Exception e) {
910 // throw new FMILException(e.getMessage());
915 // private native String getStringValue_(String id, String name);
918 // * Get an integer value for variable
919 // * @param name Name of the variable
921 // * @throws FMILException
923 // public int getIntegerValue(String name) throws FMILException {
924 // synchronized(syncObject) {
927 // return getIntegerValue_(getModelID(), name);
928 // } catch (UnsatisfiedLinkError err) {
929 // throw new FMILException(UNSATISFIED_LINK);
930 // } catch (Exception e) {
931 // throw new FMILException(e.getMessage());
936 // private native int getIntegerValue_(String id, String name);
939 // * Get a real (double) value for variable
940 // * @param name Name of the variable
942 // * @throws FMILException
944 // public boolean getBooleanValue(String name) throws FMILException {
945 // synchronized(syncObject) {
948 // return getBooleanValue_(getModelID(), name);
949 // } catch (UnsatisfiedLinkError err) {
950 // throw new FMILException(UNSATISFIED_LINK);
951 // } catch (Exception e) {
952 // throw new FMILException(e.getMessage());
957 // private native boolean getBooleanValue_(String id, String name);
959 private FileChannel channel;
960 private FileLock lock;
962 @SuppressWarnings("resource")
963 private boolean lockFMUDirectory() {
966 // Get a file channel for the lock file
967 File lockFile = new File(TEMP_FMU_DIRECTORY, LOCK_FILE_NAME);
968 if(!lockFile.isFile())
969 lockFile.createNewFile();
971 channel = new RandomAccessFile(lockFile, "rw").getChannel();
973 // Use the file channel to create a lock on the file.
974 // This method blocks until it can retrieve the lock.
975 lock = channel.lock();
977 // // Try acquiring the lock without blocking. This method returns
978 // // null or throws an exception if the file is already locked.
980 // lock = channel.tryLock();
981 // } catch (OverlappingFileLockException e) {
982 // // File is already locked in this thread or virtual machine
984 } catch (IOException e) {
991 private boolean unlockFMUDirectory() {
1000 } catch (IOException e) {
1006 private boolean removeFMUDirectoryContents() {
1009 File tempDir = new File(TEMP_FMU_DIRECTORY);
1010 FileUtils.deleteAll(tempDir);
1012 } catch (IOException e) {
1019 protected void finalize() throws Throwable {
1022 } catch (Throwable t) {
1023 LOGGER.error("Could not unload native FMU!", t);