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);
35 private static final boolean DEBUG = false;
40 private static int OK = 0;
41 private static int ERROR = 1;
42 private static int PENDING = 2;
43 private static String UNSATISFIED_LINK = "Method not found. DLL might not be loaded properly.";
44 public static final String TEMP_FMU_DIRECTORY_NAME = "fmil";
45 public static String TEMP_FMU_COMMON_DIRECTORY;
46 public static String LOCK_FILE_NAME = "fmil.lock";
48 public static Object syncObject = new Object();
51 * Static: load native libraries required for the FMU simulation to work.
55 File[] libraries = new File[2];
57 ExecEnvironment env = ExecEnvironment.calculate();
60 URL sharedFMILIBUrl = null;
61 URL simulatorFMIUrl = null;
62 Bundle b = Platform.getBundle("org.simantics.fmil.core");
64 if (env.os == OSType.WINDOWS) {
65 sharedFMILIBUrl = FileLocator.find(b, new Path("libraries/fmilib_shared.dll"), null);
66 simulatorFMIUrl = FileLocator.find(b, new Path("libraries/FMUSimulator.dll"), null);
67 } else if(env.os == OSType.LINUX) {
68 sharedFMILIBUrl = FileLocator.find(b, new Path("libraries/libfmilib_shared.so"), null);
69 simulatorFMIUrl = FileLocator.find(b, new Path("libraries/libFMUSimulator.so"), null);
72 libraries[0] = new File(FileLocator.toFileURL(sharedFMILIBUrl).getPath());
73 libraries[1] = new File(FileLocator.toFileURL(simulatorFMIUrl).getPath());
74 } catch (Exception e) {
75 LOGGER.error("Failed to resolve native FMU simulation library for execution environment {}.{}", env.os, env.arch, e);
78 for(File library : libraries) {
80 System.err.println("FMU library not loaded. FMU simulation not working.");
82 } else if(!library.isFile()) {
83 System.err.println(library.getAbsolutePath() + " not found");
86 System.load(library.getAbsolutePath());
87 } catch (Throwable t) {
88 System.err.println(t.getMessage());
95 * Static: initialize fmu temp folder from current working directory
98 TEMP_FMU_COMMON_DIRECTORY = Paths.get(".").toAbsolutePath().normalize().toString();
101 public static void setTempFMUCommonDir(File dir) {
102 TEMP_FMU_COMMON_DIRECTORY = dir.getAbsolutePath();
105 private String fmuDir;
108 public String TEMP_FOLDER_1;
109 public String TEMP_FOLDER_2;
110 public String TEMP_FMU_DIRECTORY;
111 private String dirName;
113 private String[] variableNames;
114 private String[] variableDescriptions;
115 private String[] variableDeclaredTypes;
116 private int[] variableReferences;
117 private int[] variableTypes;
118 private int[] variableCausalities;
119 private int[] variableVariabilities;
121 private String[] declaredTypes;
122 private String[] declaredTypeDescriptions;
123 private String[] declaredTypeQuantities;
124 private String[] declaredTypeUnits;
126 private static int NO_VARIABLE_KEY = -1;
128 private TObjectIntHashMap<String> variableMap = new TObjectIntHashMap<String>(10, 0.5f, NO_VARIABLE_KEY);
130 private Set<String> subscriptionSet = new HashSet<String>();
131 private TIntArrayList subscription = new TIntArrayList();
132 private ArrayList<String> subscribedNames = new ArrayList<String>();
134 public List<String> getSubscribedNames() {
135 return subscribedNames;
138 public boolean subscribe(String name) throws FMILException {
139 synchronized(syncObject) {
141 int vr = variableMap.get(name);
142 if(vr == NO_VARIABLE_KEY) return false;
143 if(!subscriptionSet.add(name)) return false;
144 subscribedNames.add(name);
145 subscription.add(vr);
146 subscribe(new int[] { vr });
152 // Create a directory for this control
153 File tempDir = new File(TEMP_FMU_COMMON_DIRECTORY, UUID.randomUUID().toString());
155 TEMP_FMU_DIRECTORY = tempDir.getAbsolutePath();
157 // Create two directories inside the temp directory for this control
158 dirName = UUID.randomUUID().toString();
159 File fmuDir = new File(TEMP_FMU_DIRECTORY, dirName);
162 TEMP_FOLDER_1 = fmuDir.toString();
163 TEMP_FOLDER_2 = fmuDir.toString() + "_2";
165 // Lock fmu directory in temp directory
169 public int getModelIDNew() {
173 public String getModelID() {
177 public String getFmuDir() {
182 * Load fmu from a given file path. Releases the (possible) previously
185 * @param path absolute file path for fmu file
186 * @throws FMILException
188 private int fmuN = 0;
189 private boolean instantiated = false;
190 public void loadFMUFile(String path) throws FMILException {
192 if (!Files.exists(Paths.get(path)))
193 throw new FMILException("File " + path + " does not exist");
194 if (!Files.isRegularFile(Paths.get(path)))
195 throw new FMILException("Path " + path + " is not a file");
197 synchronized(syncObject) {
200 fmuDir = TEMP_FOLDER_1;
203 fmuDir = TEMP_FOLDER_2;
207 java.nio.file.Path tempDir = Paths.get(fmuDir);
208 if(Files.exists(tempDir) && Files.isDirectory(tempDir)) {
210 FileUtils.emptyDirectory(tempDir);
211 } catch (IOException e) {
212 throw new FMILException("Could not delete existing files from temp folder for fmu " + path, e);
216 Files.createDirectory(tempDir);
217 } catch (IOException e) {
218 throw new FMILException("Could not create temp folder for fmu " + path, e);
223 String tmpPath = tempDir.toString();
224 if(!tmpPath.endsWith("\\") && !tmpPath.endsWith("/"))
225 tmpPath = tmpPath + "/";
226 id = loadFMUFile_(path, tmpPath);
229 getAllVariableReferences();
231 for(int i=0;i<variableNames.length;i++) {
232 variableMap.put(variableNames[i], variableReferences[i]);
235 instantiated = false;
236 } catch (UnsatisfiedLinkError err) {
237 throw new FMILException(UNSATISFIED_LINK, err);
238 } catch (Exception e) {
239 LOGGER.error(e.getMessage());
240 throw new FMILException(e.getMessage());
245 private native int loadFMUFile_(String path, String toDir) throws FMILException;
248 * Set a step length for simulation
250 * @param step Step length for simulation
251 * @throws FMILException
253 public void setStepLength(double step) throws FMILException {
254 synchronized(syncObject) {
257 int ret = setStepLength_(getModelIDNew(), step);
259 LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
261 } catch (UnsatisfiedLinkError err) {
262 throw new FMILException(UNSATISFIED_LINK);
263 } catch (Exception e) {
264 throw new FMILException(e.getMessage());
269 private native int setStepLength_(int id, double step);
272 * Instantiates a simulation.
274 * Make sure that an FMU is loaded first.
275 * @throws FMILException
277 public void instantiateSimulation() throws FMILException {
278 synchronized(syncObject) {
282 int ret = instantiateSimulation_(getModelIDNew());
284 LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
288 } catch (FMILException e) {
290 } catch (UnsatisfiedLinkError err) {
291 throw new FMILException(UNSATISFIED_LINK);
292 } catch (Exception e) {
293 throw new FMILException(e.getMessage());
298 private native int instantiateSimulation_(int id) throws FMILException;
302 * Initializes a simulation.
304 * Make sure that simulation is instantiated first!
305 * @throws FMILException
307 public void initializeSimulation() throws FMILException {
308 synchronized(syncObject) {
312 int ret = initializeSimulation_(getModelIDNew());
314 LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
316 } catch (FMILException e) {
318 } catch (UnsatisfiedLinkError err) {
319 throw new FMILException(UNSATISFIED_LINK);
320 } catch (Exception e) {
321 throw new FMILException(e.getMessage());
326 private native int initializeSimulation_(int id) throws FMILException;
329 * Subscribe a set of variables from a loaded simulation.
331 * Make sure that an FMU is loaded first.
332 * @param variables Array of variables
333 * @throws FMILException
335 public void subscribe(int[] variables) throws FMILException {
336 synchronized(syncObject) {
340 int ret = subscribe_(getModelIDNew(), variables);
342 LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
344 } catch (UnsatisfiedLinkError err) {
345 throw new FMILException(UNSATISFIED_LINK);
346 } catch (Exception e) {
347 throw new FMILException(e.getMessage());
352 private native int subscribe_(int id, int[] variables);
355 * Set value of a real variable. If the variable is a
356 * parameter, the change is effective immediately.
358 * @param name Variable name
359 * @param value New value
360 * @throws FMILException
362 public void setRealValue(String name, double value) throws FMILException {
363 int key = variableMap.get(name);
364 if(key == NO_VARIABLE_KEY)
365 throw new FMILException("No variable with name " + name);
366 setRealValue(key, value);
370 * Set value of a real variable. If the variable is a
371 * parameter, the change is effective immediately.
373 * @param name Variable id
374 * @param value New value
375 * @throws FMILException
377 public void setRealValue(int variableReference, double value) throws FMILException {
378 synchronized(syncObject) {
380 int ret = setRealValue_(getModelIDNew(), variableReference, value);
382 LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
383 } catch (FMILException e) {
385 } catch (UnsatisfiedLinkError err) {
386 throw new FMILException(UNSATISFIED_LINK);
387 } catch (Exception e) {
388 throw new FMILException(e.getMessage());
393 private native int setRealValue_(int id, int variableReference, double value) throws FMILException;
397 * Set value of an integer variable. If the variable is a
398 * parameter, the change is effective immediately.
400 * @param name Variable name
401 * @param value New value
402 * @throws FMILException
404 public void setIntegerValue(String name, int value) throws FMILException {
405 int key = variableMap.get(name);
406 if(key == NO_VARIABLE_KEY)
407 throw new FMILException("No variable with name " + name);
408 setIntegerValue(key, value);
412 * Set value of an integer variable. If the variable is a
413 * parameter, the change is effective immediately.
415 * @param name Variable id
416 * @param value New value
417 * @throws FMILException
419 public void setIntegerValue(int variableReference, int value) throws FMILException {
420 synchronized(syncObject) {
422 int ret = setIntegerValue_(getModelIDNew(), variableReference, value);
424 LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
425 } catch (FMILException e) {
427 } catch (UnsatisfiedLinkError err) {
428 throw new FMILException(UNSATISFIED_LINK);
429 } catch (Exception e) {
430 throw new FMILException(e.getMessage());
435 private native int setIntegerValue_(int id, int variableReference, int value) throws FMILException;
439 * Set value of a boolean variable. If the variable is a
440 * parameter, the change is effective immediately.
442 * @param name Variable name
443 * @param value New value
444 * @throws FMILException
446 public void setBooleanValue(String name, boolean value) throws FMILException {
447 int key = variableMap.get(name);
448 if(key == NO_VARIABLE_KEY)
449 throw new FMILException("No variable with name " + name);
450 setBooleanValue(key, value);
454 * Set value of a boolean variable. If the variable is a
455 * parameter, the change is effective immediately.
457 * @param name Variable id
458 * @param value New value
459 * @throws FMILException
461 public void setBooleanValue(int variableReference, boolean value) throws FMILException {
462 synchronized(syncObject) {
464 int ret = setBooleanValue_(getModelIDNew(), variableReference, value);
466 LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
467 } catch (FMILException e) {
469 } catch (UnsatisfiedLinkError err) {
470 throw new FMILException(UNSATISFIED_LINK);
471 } catch (Exception e) {
472 throw new FMILException(e.getMessage());
477 private native int setBooleanValue_(int id, int variableReference, boolean value) throws FMILException;
481 * Set value of a string variable. If the variable is a
482 * parameter, the change is effective immediately.
484 * @param name Variable name
485 * @param value New value
486 * @throws FMILException
488 public void setStringValue(String name, String value) throws FMILException {
489 int key = variableMap.get(name);
490 if(key == NO_VARIABLE_KEY)
491 throw new FMILException("No variable with name " + name);
492 setStringValue(key, value);
496 * Set value of a string variable. If the variable is a
497 * parameter, the change is effective immediately.
499 * @param name Variable id
500 * @param value New value
501 * @throws FMILException
503 public void setStringValue(int variableReference, String value) throws FMILException {
504 synchronized(syncObject) {
506 int ret = setStringValue_(getModelIDNew(), variableReference, value);
508 LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
509 } catch (FMILException e) {
511 } catch (UnsatisfiedLinkError err) {
512 throw new FMILException(UNSATISFIED_LINK);
513 } catch (Exception e) {
514 throw new FMILException(e.getMessage());
519 private native int setStringValue_(int id, int variableReference, String value) throws FMILException;
523 * Simulate one step forward. The step length can be set with
526 * @throws FMILException
528 public void simulateStep() throws FMILException {
529 synchronized(syncObject) {
533 int ret = simulateStep_(getModelIDNew()); //0 is ok, 1 is error, 2 is pending
535 LOGGER.warn("Pending status return from FMU. This is not implemented in our Simulator yet!");
537 LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
538 } catch (FMILException e) {
540 } catch (UnsatisfiedLinkError err) {
541 throw new FMILException(UNSATISFIED_LINK);
542 } catch (Exception e) {
543 throw new FMILException(e.getMessage());
547 private native int simulateStep_(int id) throws FMILException;
550 * Get an array containing the current values for subscribed variables. The
551 * values are in the same order as in the subscription.
553 * @param results An array the size of subscribed results
556 public double[] getSubscribedResults() throws FMILException {
557 synchronized(syncObject) {
561 double[] results = new double[subscription.size()];
562 Arrays.fill(results, Double.NaN);
564 return getSubscribedResults_(getModelIDNew(), results);
565 } catch (UnsatisfiedLinkError err) {
566 throw new FMILException(UNSATISFIED_LINK);
567 } catch (Exception e) {
568 throw new FMILException(e.getMessage());
573 private native double[] getSubscribedResults_(int id, double[] results);
577 * Unload FMU and the dll:s that it requires.
579 * To be called after all FMU simulations are ended.
580 * If the fmu is loaded again / changed, call to loadFMUFile is sufficient. loadFMUFile
581 * releases the previous fmu.dll
583 * @throws FMILException
585 public void unloadFMU() throws FMILException {
586 synchronized(syncObject) {
590 unlockFMUDirectory();
592 // Many FMUs will not correctly clean-up during unload if the simulation isn't instantiated
593 // Essentially we'd likely be passing an invalid pointer to the FMU to cleanup, causing native c-level crashes.
596 int ret = unloadFMU_(getModelIDNew());
598 LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
599 instantiated = false;
601 removeFMUDirectoryContents();
603 } catch (FMILException e) {
605 } catch (UnsatisfiedLinkError err) {
606 throw new FMILException(UNSATISFIED_LINK);
607 } catch (Exception e) {
608 throw new FMILException(e.getMessage());
612 private native int unloadFMU_(int id) throws FMILException;
615 // * Checks if fmu has been initialized
616 // * @return current simulation time
618 // public boolean isInitialized() throws FMILException {
619 // synchronized(syncObject) {
621 // return isInitialized_(getModelID());
622 // } catch (UnsatisfiedLinkError err) {
623 // throw new FMILException(UNSATISFIED_LINK);
624 // } catch (Exception e) {
625 // throw new FMILException(e.getMessage());
630 // private native boolean isInitialized_(String id);
633 * Get the current simulation time
634 * @return current simulation time
636 public double getTime() throws FMILException {
637 synchronized(syncObject) {
641 return getTime_(getModelIDNew());
643 } catch (UnsatisfiedLinkError err) {
644 throw new FMILException(UNSATISFIED_LINK);
645 } catch (Exception e) {
646 throw new FMILException(e.getMessage());
651 private native double getTime_(int id);
654 * Get all variables in a loaded model
655 * @return all variables in a loaded model
657 public String[] getAllVariables() throws FMILException {
658 synchronized(syncObject) {
662 if(variableNames == null) {
663 variableNames = getAllVariables_(getModelIDNew());
665 return variableNames;
667 } catch (UnsatisfiedLinkError err) {
668 throw new FMILException(UNSATISFIED_LINK);
669 } catch (Exception e) {
670 throw new FMILException(e.getMessage());
675 private native String[] getAllVariables_(int id);
677 public String[] getAllVariableDescriptions() throws FMILException {
678 synchronized(syncObject) {
682 if(variableDescriptions == null) {
683 variableDescriptions = getAllVariableDescriptions_(getModelIDNew());
685 return variableDescriptions;
687 } catch (UnsatisfiedLinkError err) {
688 throw new FMILException(UNSATISFIED_LINK);
689 } catch (Exception e) {
690 throw new FMILException(e.getMessage());
695 private native String[] getAllVariableDescriptions_(int id);
697 public String[] getAllVariableDeclaredTypes() throws FMILException {
698 synchronized(syncObject) {
702 if(variableDeclaredTypes == null) {
703 variableDeclaredTypes = getAllVariableDeclaredTypes_(getModelIDNew());
705 return variableDeclaredTypes;
707 } catch (UnsatisfiedLinkError err) {
708 throw new FMILException(UNSATISFIED_LINK);
709 } catch (Exception e) {
710 throw new FMILException(e.getMessage());
715 private native String[] getAllVariableDeclaredTypes_(int id);
717 public int[] getAllVariableReferences() throws FMILException {
718 synchronized(syncObject) {
722 if(variableReferences == null) {
723 variableReferences = getAllVariableReferences_(getModelIDNew(), new int[variableNames.length]);
725 return variableReferences;
727 } catch (UnsatisfiedLinkError err) {
728 throw new FMILException(UNSATISFIED_LINK);
729 } catch (Exception e) {
730 throw new FMILException(e.getMessage());
735 private native int[] getAllVariableReferences_(int id, int[] array);
737 public int[] getAllVariableTypes() throws FMILException {
738 synchronized(syncObject) {
742 if(variableTypes == null) {
743 variableTypes = getAllVariableTypes_(getModelIDNew(), new int[variableNames.length]);
745 return variableTypes;
747 } catch (UnsatisfiedLinkError err) {
748 throw new FMILException(UNSATISFIED_LINK);
749 } catch (Exception e) {
750 throw new FMILException(e.getMessage());
755 private native int[] getAllVariableTypes_(int id, int[] array);
757 public int[] getAllVariableCausalities() throws FMILException {
758 synchronized(syncObject) {
762 if(variableCausalities == null) {
763 variableCausalities = getAllVariableCausalities_(getModelIDNew(), new int[variableNames.length]);
765 return variableCausalities;
767 } catch (UnsatisfiedLinkError err) {
768 throw new FMILException(UNSATISFIED_LINK);
769 } catch (Exception e) {
770 throw new FMILException(e.getMessage());
775 private native int[] getAllVariableCausalities_(int id, int[] array);
777 public int[] getAllVariableVariabilities() throws FMILException {
778 synchronized(syncObject) {
782 if(variableVariabilities == null) {
783 variableVariabilities = getAllVariableVariabilities_(getModelIDNew(), new int[variableNames.length]);
785 return variableVariabilities;
787 } catch (UnsatisfiedLinkError err) {
788 throw new FMILException(UNSATISFIED_LINK);
789 } catch (Exception e) {
790 throw new FMILException(e.getMessage());
795 private native int[] getAllVariableVariabilities_(int id, int[] array);
798 * Get all variables in a loaded model
799 * @return all variables in a loaded model
801 public String[] getAllDeclaredTypes() throws FMILException {
802 synchronized(syncObject) {
806 if(declaredTypes == null) {
807 declaredTypes = getAllDeclaredTypes_(getModelIDNew());
809 return declaredTypes;
811 } catch (UnsatisfiedLinkError err) {
812 throw new FMILException(UNSATISFIED_LINK);
813 } catch (Exception e) {
814 throw new FMILException(e.getMessage());
819 private native String[] getAllDeclaredTypes_(int id);
821 public String[] getAllDeclaredTypeDescriptions() throws FMILException {
822 synchronized(syncObject) {
826 if(declaredTypeDescriptions == null) {
827 declaredTypeDescriptions = getAllDeclaredTypeDescriptions_(getModelIDNew());
829 return declaredTypeDescriptions;
831 } catch (UnsatisfiedLinkError err) {
832 throw new FMILException(UNSATISFIED_LINK);
833 } catch (Exception e) {
834 throw new FMILException(e.getMessage());
839 private native String[] getAllDeclaredTypeDescriptions_(int id);
841 public String[] getAllDeclaredTypeQuantities() throws FMILException {
842 synchronized(syncObject) {
846 if(declaredTypeQuantities == null) {
847 declaredTypeQuantities = getAllDeclaredTypeQuantities_(getModelIDNew());
849 return declaredTypeQuantities;
851 } catch (UnsatisfiedLinkError err) {
852 throw new FMILException(UNSATISFIED_LINK);
853 } catch (Exception e) {
854 throw new FMILException(e.getMessage());
859 private native String[] getAllDeclaredTypeQuantities_(int id);
861 public String[] getAllDeclaredTypeUnits() throws FMILException {
862 synchronized(syncObject) {
866 if(declaredTypeUnits == null) {
867 declaredTypeUnits = getAllDeclaredTypeUnits_(getModelIDNew());
869 return declaredTypeUnits;
871 } catch (UnsatisfiedLinkError err) {
872 throw new FMILException(UNSATISFIED_LINK);
873 } catch (Exception e) {
874 throw new FMILException(e.getMessage());
879 private native String[] getAllDeclaredTypeUnits_(int id);
884 // * Get all variables from model that match the filter (and time variable)
886 // * @param regexp Regular expression filter
887 // * @return An array of variable names that match regexp filter (and time-variable)
888 // * @throws FMILException
890 // public String[] filterVariables(String regexp) throws FMILException {
891 // synchronized(syncObject) {
894 // return filterVariables_(getModelID(), regexp + "|time");
896 // } catch (UnsatisfiedLinkError err) {
897 // throw new FMILException(UNSATISFIED_LINK);
898 // } catch (Exception e) {
899 // throw new FMILException(e.getMessage());
904 // private native String[] filterVariables_(String id, String regexp);
907 // * Get the last error message
908 // * @return Last error message
910 // public String getLastErrorMessage() throws FMILException {
911 // synchronized(syncObject) {
916 // //return getLastErrorMessage_(getModelID());
918 // } catch (UnsatisfiedLinkError err) {
919 // throw new FMILException(UNSATISFIED_LINK);
920 // } catch (Exception e) {
921 // throw new FMILException(e.getMessage());
926 // private native String getLastErrorMessage_(String id);
929 * Get a value (double) for real variable
930 * @param name Name of the variable
932 * @throws FMILException
934 public double getRealValue(String name) throws FMILException {
935 int key = variableMap.get(name);
936 if(key == NO_VARIABLE_KEY)
937 throw new FMILException("No variable with name " + name);
938 double result = getRealValue(key);
939 if (DEBUG) System.err.println("getRealValue " + name + " = " + result);
944 * Get a value (double) for real variable
945 * @param variableReference Numeric id of the variable
947 * @throws FMILException
949 public double getRealValue(int variableReference) throws FMILException {
950 synchronized(syncObject) {
952 return getRealValue_(getModelIDNew(), variableReference);
953 } catch (UnsatisfiedLinkError err) {
954 throw new FMILException(UNSATISFIED_LINK);
955 } catch (Exception e) {
956 throw new FMILException(e.getMessage());
961 private native double getRealValue_(int id, int variableReference) throws FMILException;
965 * Get value of integer variable
966 * @param name Name of the variable
968 * @throws FMILException
970 public int getIntegerValue(String name) throws FMILException {
971 int key = variableMap.get(name);
972 if(key == NO_VARIABLE_KEY)
973 throw new FMILException("No variable with name " + name);
974 int result = getIntegerValue(key);
975 if (DEBUG) System.err.println("getIntegerValue " + name + " = " + result);
980 * Get a real (double) value for variable
981 * @param variableReference Numeric id of the variable
983 * @throws FMILException
985 public int getIntegerValue(int variableReference) throws FMILException {
986 synchronized(syncObject) {
988 return getIntegerValue_(getModelIDNew(), variableReference);
989 } catch (UnsatisfiedLinkError err) {
990 throw new FMILException(UNSATISFIED_LINK);
991 } catch (Exception e) {
992 throw new FMILException(e.getMessage());
997 private native int getIntegerValue_(int id, int variableReference) throws FMILException;
1001 * Get value of boolean variable
1002 * @param name Name of the variable
1004 * @throws FMILException
1006 public boolean getBooleanValue(String name) throws FMILException {
1007 int key = variableMap.get(name);
1008 if(key == NO_VARIABLE_KEY)
1009 throw new FMILException("No variable with name " + name);
1010 boolean result = getBooleanValue(key);
1011 if (DEBUG) System.err.println("getBooleanValue " + name + " = " + result);
1016 * Get value of boolean variable
1017 * @param variableReference Numeric id of the variable
1019 * @throws FMILException
1021 public boolean getBooleanValue(int variableReference) throws FMILException {
1022 synchronized(syncObject) {
1024 return getBooleanValue_(getModelIDNew(), variableReference);
1025 } catch (UnsatisfiedLinkError err) {
1026 throw new FMILException(UNSATISFIED_LINK);
1027 } catch (Exception e) {
1028 throw new FMILException(e.getMessage());
1033 private native boolean getBooleanValue_(int id, int variableReference) throws FMILException;
1037 * Get value of string variable
1038 * @param name Name of the variable
1040 * @throws FMILException
1042 public String getStringValue(String name) throws FMILException {
1043 int key = variableMap.get(name);
1044 if(key == NO_VARIABLE_KEY)
1045 throw new FMILException("No variable with name " + name);
1046 String result = getStringValue(key);
1047 if (DEBUG) System.err.println("getIntegerValue " + name + " = " + result);
1052 * Get value of string variable
1053 * @param variableReference Numeric id of the variable
1055 * @throws FMILException
1057 public String getStringValue(int variableReference) throws FMILException {
1058 synchronized(syncObject) {
1060 return getStringValue_(getModelIDNew(), variableReference);
1061 } catch (UnsatisfiedLinkError err) {
1062 throw new FMILException(UNSATISFIED_LINK);
1063 } catch (Exception e) {
1064 throw new FMILException(e.getMessage());
1069 private native String getStringValue_(int id, int variableReference) throws FMILException;
1072 private FileChannel channel;
1073 private FileLock lock;
1075 @SuppressWarnings("resource")
1076 private boolean lockFMUDirectory() {
1079 // Get a file channel for the lock file
1080 File lockFile = new File(TEMP_FMU_DIRECTORY, LOCK_FILE_NAME);
1081 if(!lockFile.isFile())
1082 lockFile.createNewFile();
1084 channel = new RandomAccessFile(lockFile, "rw").getChannel();
1086 // Use the file channel to create a lock on the file.
1087 // This method blocks until it can retrieve the lock.
1088 lock = channel.lock();
1090 // // Try acquiring the lock without blocking. This method returns
1091 // // null or throws an exception if the file is already locked.
1093 // lock = channel.tryLock();
1094 // } catch (OverlappingFileLockException e) {
1095 // // File is already locked in this thread or virtual machine
1097 } catch (IOException e) {
1104 private boolean unlockFMUDirectory() {
1113 } catch (IOException e) {
1119 private boolean removeFMUDirectoryContents() {
1122 File tempDir = new File(TEMP_FMU_DIRECTORY);
1123 FileUtils.deleteAll(tempDir);
1125 } catch (IOException e) {
1132 protected void finalize() throws Throwable {
1135 } catch (Throwable t) {
1136 LOGGER.error("Could not unload native FMU!", t);