]> gerrit.simantics Code Review - simantics/fmil.git/blob - org.simantics.fmil.core/src/org/simantics/fmil/core/FMIL.java
Added placeholder for FMIL linux64 fragment
[simantics/fmil.git] / org.simantics.fmil.core / src / org / simantics / fmil / core / FMIL.java
1 package org.simantics.fmil.core;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.io.RandomAccessFile;
6 import java.nio.channels.FileChannel;
7 import java.nio.channels.FileLock;
8 import java.nio.file.Paths;
9 import java.util.ArrayList;
10 import java.util.HashSet;
11 import java.util.List;
12 import java.util.Set;
13 import java.util.UUID;
14
15 import org.eclipse.core.runtime.FileLocator;
16 import org.eclipse.core.runtime.Platform;
17 import org.osgi.framework.Bundle;
18 import org.simantics.fmil.core.ExecEnvironment.ARCHType;
19 import org.simantics.fmil.core.ExecEnvironment.OSType;
20 import org.simantics.utils.FileUtils;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24 import gnu.trove.list.array.TIntArrayList;
25 import gnu.trove.map.hash.TObjectIntHashMap;
26
27
28 public class FMIL {
29
30     private static final Logger LOGGER = LoggerFactory.getLogger(FMIL.class);
31
32     /**
33      * Static variables
34      */
35     private static int      OK                  = 0;
36     private static int      ERROR               = 1;
37     private static String   UNSATISFIED_LINK    = "Method not found. DLL might not be loaded properly.";      
38     public static final String TEMP_FMU_DIRECTORY_NAME = "fmil";  
39     public static String    TEMP_FMU_COMMON_DIRECTORY;  
40     public static String    LOCK_FILE_NAME      = "fmil.lock";
41
42     public static Object syncObject = new Object();
43
44     /**
45      * Static: load native libraries required for the FMU simulation to work.
46      */
47     static {
48         
49         File[] libraries = new File[2];
50
51         Bundle bundle = null;
52         
53         ExecEnvironment env = ExecEnvironment.calculate();
54         if (env.os == OSType.WINDOWS) {
55             if (env.arch == ARCHType.X86) {
56                 bundle = Platform.getBundle("org.simantics.fmil.win32");
57             } else if (env.arch == ARCHType.X86_64) {
58                 bundle = Platform.getBundle("org.simantics.fmil.win64");
59             }
60         }
61         
62         if (bundle != null) {
63             try{
64                 String root = FileLocator.getBundleFile(bundle).getAbsolutePath();
65 //                if (env.arch == ARCHType.X86_64) {
66 //                    File newFIle = new File(root, "libraries/libexpat.dll");
67 //                    System.load(newFIle.getAbsolutePath());
68 //                }
69 //                libraries[0] = new File(root, "libraries/zlibwapi.dll");
70 //                libraries[1] = new File(root, "libraries/miniunz.dll");
71                 libraries[0] = new File(root, "libraries/fmilib_shared.dll");
72                 libraries[1] = new File(root, "libraries/FMUSimulator.dll");
73             }
74             catch (Exception e) {
75                 e.printStackTrace();
76             }
77         }
78
79         for(File library : libraries) {
80             if(library == null) {
81                 System.err.println("FMU library not loaded. FMU simulation not working.");
82                 continue;
83             } else if(!library.isFile()) {
84                 System.err.println(library.getAbsolutePath() + " not found");
85             } else {
86                 try {
87                     System.load(library.getAbsolutePath());
88                 } catch (Throwable t) {
89                     System.err.println(t.getMessage());
90                 }
91             } 
92         }
93     }
94
95     /**
96      * Static: initialize fmu temp folder from current working directory
97      */
98     static {
99         TEMP_FMU_COMMON_DIRECTORY = Paths.get(".").toAbsolutePath().normalize().toString();
100     }
101     
102     public static void setTempFMUCommonDir(File dir) {
103         TEMP_FMU_COMMON_DIRECTORY = dir.getAbsolutePath(); 
104     }
105
106     private String fmuDir;
107     private int id;
108
109     public String TEMP_FOLDER_1;
110     public String TEMP_FOLDER_2;
111     public String TEMP_FMU_DIRECTORY;
112     private String dirName;
113
114         private String[] variableNames;
115         private String[] variableDescriptions;
116         private String[] variableDeclaredTypes;
117         private int[] variableReferences;
118         private int[] variableTypes;
119         private int[] variableCausalities;
120         private int[] variableVariabilities;
121         
122         private String[] declaredTypes;
123         private String[] declaredTypeDescriptions;
124         private String[] declaredTypeQuantities;
125         private String[] declaredTypeUnits;
126         
127         private TObjectIntHashMap<String> variableMap = new TObjectIntHashMap<String>();
128         
129         private Set<String> subscriptionSet = new HashSet<String>();
130         private TIntArrayList subscription = new TIntArrayList();
131         private ArrayList<String> subscribedNames = new ArrayList<String>();
132         
133         public List<String> getSubscribedNames() {
134                 return subscribedNames;
135         }
136         
137         public boolean subscribe(String name) throws FMILException {
138                 // Safety check
139                 int vr = variableMap.get(name);
140                 if(vr == 0) return false;
141                 if(!subscriptionSet.add(name)) return false;
142                 subscribedNames.add(name);
143                 System.err.println("subscribed : " + name + " => " + subscribedNames.size());
144                 subscription.add(vr);
145                 subscribe(new int[] { vr });
146                 return true;
147         }
148
149     public FMIL() {
150         // Create a directory for this control
151         File tempDir = new File(TEMP_FMU_COMMON_DIRECTORY, UUID.randomUUID().toString());
152         tempDir.mkdir();
153         TEMP_FMU_DIRECTORY = tempDir.getAbsolutePath();
154
155         // Create two directories inside the temp directory for this control
156         dirName = UUID.randomUUID().toString();
157         File fmuDir = new File(TEMP_FMU_DIRECTORY, dirName);
158         fmuDir.mkdir();
159
160         TEMP_FOLDER_1 = fmuDir.toString();
161         TEMP_FOLDER_2 = fmuDir.toString() + "_2";
162
163         // Lock fmu directory in temp directory
164         lockFMUDirectory();
165     }
166
167     public int getModelIDNew() {
168         return id;
169     }
170
171     public String getModelID() {
172         return dirName;
173     }
174
175     public String getFmuDir() {
176         return fmuDir;
177     }
178
179     /**
180      * Load fmu from a given file path. Releases the (possible) previously
181      * loaded fmu.
182      * 
183      * @param path absolute file path for fmu file
184      * @throws FMILException
185      */
186     private int fmuN = 0;
187     private boolean fmuLoaded = false;
188     public void loadFMUFile(String path) throws FMILException {
189
190         synchronized(syncObject) {
191
192             if(fmuN % 2 == 0) {
193                 fmuDir = TEMP_FOLDER_1;
194                 fmuN++;
195             } else {
196                 fmuDir = TEMP_FOLDER_2;
197                 fmuN = 0;
198             }
199
200             File tempDir = new File(fmuDir);
201             if(tempDir.isDirectory()) {
202                 try {
203                     FileUtils.deleteAll(tempDir);
204                 } catch (IOException e) {
205                     throw new FMILException("Could not create temp folder for fmu");
206                 }
207                 tempDir.mkdir();
208             } else {
209                 tempDir.mkdir();
210             }
211
212
213             try {
214                 String tmpPath = tempDir.getAbsolutePath();
215                 if(!tmpPath.endsWith("\\"))
216                     tmpPath = tmpPath + "\\";
217                 id = loadFMUFile_(path, tmpPath);
218                 
219                 getAllVariables();
220                 getAllVariableReferences();
221                 
222                 for(int i=0;i<variableNames.length;i++) {
223                         variableMap.put(variableNames[i], variableReferences[i]);
224                 }
225
226                 fmuLoaded = true;
227             } catch (UnsatisfiedLinkError err) {
228                 throw new FMILException(UNSATISFIED_LINK, err);
229             } catch (Exception e) {
230                 throw new FMILException(e.getMessage());
231             }
232         }
233     }
234
235     private native int loadFMUFile_(String path, String toDir);
236
237     /**
238      * Set a step length for simulation
239      * 
240      * @param step Step length for simulation
241      * @throws FMILException
242      */
243     public void setStepLength(double step) throws FMILException {
244         synchronized(syncObject) {
245
246             try {
247                 int ret = setStepLength_(getModelIDNew(), step);
248                 if(ret != OK)
249                     LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
250
251             } catch (UnsatisfiedLinkError err) {
252                 throw new FMILException(UNSATISFIED_LINK);
253             } catch (Exception e) {
254                 throw new FMILException(e.getMessage());
255             }
256         }
257     }
258
259     private native int setStepLength_(int id, double step);
260
261     /**
262      * Instantiates a simulation. 
263      * <p>
264      * Make sure that an FMU is loaded first.
265      * @throws FMILException
266      */
267     public void instantiateSimulation() throws FMILException {
268         synchronized(syncObject) {
269
270             try {
271
272                 int ret = instantiateSimulation_(getModelIDNew()); 
273                 if(ret != OK)
274                     LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
275
276             } catch (FMILException e) {
277                 throw e;
278             } catch (UnsatisfiedLinkError err) {
279                 throw new FMILException(UNSATISFIED_LINK);
280             } catch (Exception e) {
281                 throw new FMILException(e.getMessage());
282             }
283         }
284     }
285
286     private native int instantiateSimulation_(int id) throws FMILException;
287
288     
289     /**
290      * Initializes a simulation. 
291      * <p>
292      * Make sure that simulation is instantiated first!
293      * @throws FMILException
294      */
295     public void initializeSimulation() throws FMILException {
296         synchronized(syncObject) {
297
298             try {
299
300                 int ret = initializeSimulation_(getModelIDNew()); 
301                 if(ret != OK)
302                     LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
303
304             } catch (FMILException e) {
305                 throw e;
306             } catch (UnsatisfiedLinkError err) {
307                 throw new FMILException(UNSATISFIED_LINK);
308             } catch (Exception e) {
309                 throw new FMILException(e.getMessage());
310             }
311         }
312     }
313
314     private native int initializeSimulation_(int id) throws FMILException;
315
316     /**
317      * Subscribe a set of variables from a loaded simulation.
318      * <p>
319      * Make sure that an FMU is loaded first.
320      * @param variables Array of variables
321      * @throws FMILException
322      */
323     public void subscribe(int[] variables) throws FMILException {
324         synchronized(syncObject) {
325
326             try {
327
328                 int ret = subscribe_(getModelIDNew(), variables); 
329                 if(ret != OK)
330                     LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
331
332             } catch (UnsatisfiedLinkError err) {
333                 throw new FMILException(UNSATISFIED_LINK);
334             } catch (Exception e) {
335                 throw new FMILException(e.getMessage());
336             }
337         }
338     }
339
340     private native int subscribe_(int id, int[] variables);
341
342     /**
343      * Set a new (Real, double) value for a variable. If the variable is a 
344      * parameter, the change is effective immediately.
345      *  
346      * @param name Variable
347      * @param value New (Real, double) value
348      * @throws FMILException
349      */
350     public void setRealValue(String name, double value) throws FMILException {
351         
352         synchronized(syncObject) {
353
354             try {
355
356                 int ret = setRealValue_(getModelIDNew(), variableMap.get(name), value); 
357                 if(ret != OK)
358                     LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
359
360             } catch (FMILException e) {
361                 throw e;
362             } catch (UnsatisfiedLinkError err) {
363                 throw new FMILException(UNSATISFIED_LINK);
364             } catch (Exception e) {
365                 throw new FMILException(e.getMessage());
366             }
367             
368         }
369         
370     }
371
372     public void setRealValue(int variableReference, double value) throws FMILException {
373         
374         synchronized(syncObject) {
375
376             try {
377
378                 int ret = setRealValue_(getModelIDNew(), variableReference, value); 
379                 if(ret != OK)
380                     LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
381
382             } catch (FMILException e) {
383                 throw e;
384             } catch (UnsatisfiedLinkError err) {
385                 throw new FMILException(UNSATISFIED_LINK);
386             } catch (Exception e) {
387                 throw new FMILException(e.getMessage());
388             }
389             
390         }
391         
392     }
393
394     private native int setRealValue_(int id, int variableReference, double value) throws FMILException;
395
396 //    /**
397 //     * Set a new (integer) value for a variable. If the variable is a 
398 //     * parameter, the change is effective immediately.
399 //     *  
400 //     * @param name Variable
401 //     * @param value New (integer) value
402 //     * @throws FMILException
403 //     */
404 //    public void setIntegerValue(String name, int value) throws FMILException {
405 //        synchronized(syncObject) {
406 //
407 //            try {
408 //
409 //                int ret = setIntegerValue_(getModelID(), name, value); 
410 //                if(ret == ERROR)
411 //                    throw new FMILException(getLastErrorMessage());
412 //
413 //            } catch (UnsatisfiedLinkError err) {
414 //                throw new FMILException(UNSATISFIED_LINK);
415 //            } catch (Exception e) {
416 //                throw new FMILException(e.getMessage());
417 //            }
418 //        }
419 //    }
420 //    private native int setIntegerValue_(String id, String name, int value);
421 //
422 //    /**
423 //     * Set a new (boolean) value for a variable. If the variable is a 
424 //     * parameter, the change is effective immediately.
425 //     *  
426 //     * @param name Variable
427 //     * @param value New (boolean) value
428 //     * @throws FMILException
429 //     */
430 //    public void setBooleanValue(String name, boolean value) throws FMILException {
431 //        synchronized(syncObject) {
432 //
433 //            try {
434 //
435 //                int ret = setBooleanValue_(getModelID(), name, value); 
436 //                if(ret == ERROR)
437 //                    throw new FMILException(getLastErrorMessage());
438 //
439 //            } catch (UnsatisfiedLinkError err) {
440 //                throw new FMILException(UNSATISFIED_LINK);
441 //            } catch (Exception e) {
442 //                throw new FMILException(e.getMessage());
443 //            }
444 //        }
445 //    }
446 //    private native int setBooleanValue_(String id, String name, boolean value);
447 //
448 //    public void setTime(double time) throws FMILException {
449 //        synchronized(syncObject) {
450 //
451 //            try {
452 //
453 //                int ret = setTime_(getModelID(), time); 
454 //                if(ret == ERROR)
455 //                    throw new FMILException(getLastErrorMessage());
456 //
457 //            } catch (UnsatisfiedLinkError err) {
458 //                throw new FMILException(UNSATISFIED_LINK);
459 //            } catch (Exception e) {
460 //                throw new FMILException(e.getMessage());
461 //            }
462 //        }
463 //    }
464 //    private native int setTime_(String id, double time);
465
466     /**
467      * Simulate one step forward. The step length can be set with
468      * setStepLength()
469      * 
470      * @throws FMILException
471      */
472     public void simulateStep() throws FMILException {
473         synchronized(syncObject) {
474
475             try {
476
477                 int ret = simulateStep_(getModelIDNew()); 
478                 if(ret != OK)
479                     LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
480
481             } catch (FMILException e) {
482                 throw e;
483             } catch (UnsatisfiedLinkError err) {
484                 throw new FMILException(UNSATISFIED_LINK);
485             } catch (Exception e) {
486                 throw new FMILException(e.getMessage());
487             }
488         }
489     }
490     private native int simulateStep_(int id) throws FMILException;
491
492     /**
493      * Get an array containing the current values for subscribed variables. The
494      * values are in the same order as in the subscription.
495      * 
496      * @param results An array the size of subscribed results
497      * @return
498      */
499     public double[] getSubscribedResults() throws FMILException {
500         synchronized(syncObject) {
501
502             try {
503
504                 double[] results = new double[subscription.size()];
505                 return getSubscribedResults_(getModelIDNew(), results);
506
507             } catch (UnsatisfiedLinkError err) {
508                 throw new FMILException(UNSATISFIED_LINK);
509             } catch (Exception e) {
510                 throw new FMILException(e.getMessage());
511             }
512         }
513     }
514
515     private native double[] getSubscribedResults_(int id, double[] results);
516     
517
518     /**
519      * Unload FMU and the dll:s that it requires.
520      * <p>
521      * To be called after all FMU simulations are ended. 
522      * If the fmu is loaded again / changed, call to loadFMUFile is sufficient. loadFMUFile 
523      * releases the previous fmu.dll  
524      * 
525      * @throws FMILException
526      */
527     public void unloadFMU() throws FMILException {
528         synchronized(syncObject) {
529
530             try {
531
532                 unlockFMUDirectory();
533                 if(fmuLoaded) {
534                     int ret = unloadFMU_(getModelIDNew()); 
535                     if(ret != OK)
536                         LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
537                     fmuLoaded = false;
538                 }
539                 removeFMUDirectoryContents();
540
541             } catch (FMILException e) {
542                 throw e;
543             } catch (UnsatisfiedLinkError err) {
544                 throw new FMILException(UNSATISFIED_LINK);
545             } catch (Exception e) {
546                 throw new FMILException(e.getMessage());
547             }
548         }
549     }
550     private native int unloadFMU_(int id) throws FMILException;
551     
552 //    /**
553 //     * Checks if fmu has been initialized
554 //     * @return current simulation time
555 //     */
556 //    public boolean isInitialized() throws FMILException {
557 //        synchronized(syncObject) {
558 //            try {
559 //                return isInitialized_(getModelID());
560 //            } catch (UnsatisfiedLinkError err) {
561 //                throw new FMILException(UNSATISFIED_LINK);
562 //            } catch (Exception e) {
563 //                throw new FMILException(e.getMessage());
564 //            }
565 //        }
566 //    }
567 //
568 //    private native boolean isInitialized_(String id);
569 //
570     /**
571      * Get the current simulation time
572      * @return current simulation time
573      */
574     public double getTime() throws FMILException {
575         synchronized(syncObject) {
576
577             try {
578
579                 return getTime_(getModelIDNew());
580
581             } catch (UnsatisfiedLinkError err) {
582                 throw new FMILException(UNSATISFIED_LINK);
583             } catch (Exception e) {
584                 throw new FMILException(e.getMessage());
585             }
586         }
587     }
588
589     private native double getTime_(int id);
590
591     /**
592      * Get all variables in a loaded model
593      * @return all variables in a loaded model
594      */
595     public String[] getAllVariables() throws FMILException {
596         synchronized(syncObject) {
597
598             try {
599
600                 if(variableNames == null) {
601                         variableNames = getAllVariables_(getModelIDNew());
602                 }
603                 return variableNames;
604
605             } catch (UnsatisfiedLinkError err) {
606                 throw new FMILException(UNSATISFIED_LINK);
607             } catch (Exception e) {
608                 throw new FMILException(e.getMessage());
609             }
610         }
611     }
612
613     private native String[] getAllVariables_(int id);
614
615     public String[] getAllVariableDescriptions() throws FMILException {
616         synchronized(syncObject) {
617
618             try {
619
620                 if(variableDescriptions == null) {
621                         variableDescriptions = getAllVariableDescriptions_(getModelIDNew());
622                 }
623                 return variableDescriptions;
624
625             } catch (UnsatisfiedLinkError err) {
626                 throw new FMILException(UNSATISFIED_LINK);
627             } catch (Exception e) {
628                 throw new FMILException(e.getMessage());
629             }
630         }
631     }
632
633     private native String[] getAllVariableDescriptions_(int id);
634     
635     public String[] getAllVariableDeclaredTypes() throws FMILException {
636         synchronized(syncObject) {
637
638             try {
639
640                 if(variableDeclaredTypes == null) {
641                         variableDeclaredTypes = getAllVariableDeclaredTypes_(getModelIDNew());
642                 }
643                 return variableDeclaredTypes;
644
645             } catch (UnsatisfiedLinkError err) {
646                 throw new FMILException(UNSATISFIED_LINK);
647             } catch (Exception e) {
648                 throw new FMILException(e.getMessage());
649             }
650         }
651     }
652
653     private native String[] getAllVariableDeclaredTypes_(int id);
654
655     public int[] getAllVariableReferences() throws FMILException {
656         synchronized(syncObject) {
657
658             try {
659
660                 if(variableReferences == null) {
661                         variableReferences = getAllVariableReferences_(getModelIDNew(), new int[variableNames.length]); 
662                 }
663                 return variableReferences;
664
665             } catch (UnsatisfiedLinkError err) {
666                 throw new FMILException(UNSATISFIED_LINK);
667             } catch (Exception e) {
668                 throw new FMILException(e.getMessage());
669             }
670         }
671     }
672
673     private native int[] getAllVariableReferences_(int id, int[] array);
674
675     public int[] getAllVariableTypes() throws FMILException {
676         synchronized(syncObject) {
677
678             try {
679
680                 if(variableTypes == null) {
681                         variableTypes = getAllVariableTypes_(getModelIDNew(), new int[variableNames.length]); 
682                 }
683                 return variableTypes;
684
685             } catch (UnsatisfiedLinkError err) {
686                 throw new FMILException(UNSATISFIED_LINK);
687             } catch (Exception e) {
688                 throw new FMILException(e.getMessage());
689             }
690         }
691     }
692
693     private native int[] getAllVariableTypes_(int id, int[] array);
694
695     public int[] getAllVariableCausalities() throws FMILException {
696         synchronized(syncObject) {
697
698             try {
699
700                 if(variableCausalities == null) {
701                         variableCausalities = getAllVariableCausalities_(getModelIDNew(), new int[variableNames.length]); 
702                 }
703                 return variableCausalities;
704
705             } catch (UnsatisfiedLinkError err) {
706                 throw new FMILException(UNSATISFIED_LINK);
707             } catch (Exception e) {
708                 throw new FMILException(e.getMessage());
709             }
710         }
711     }
712
713     private native int[] getAllVariableCausalities_(int id, int[] array);
714
715     public int[] getAllVariableVariabilities() throws FMILException {
716         synchronized(syncObject) {
717
718             try {
719
720                 if(variableVariabilities == null) {
721                         variableVariabilities = getAllVariableVariabilities_(getModelIDNew(), new int[variableNames.length]); 
722                 }
723                 return variableVariabilities;
724
725             } catch (UnsatisfiedLinkError err) {
726                 throw new FMILException(UNSATISFIED_LINK);
727             } catch (Exception e) {
728                 throw new FMILException(e.getMessage());
729             }
730         }
731     }
732
733     private native int[] getAllVariableVariabilities_(int id, int[] array);
734
735     /**
736      * Get all variables in a loaded model
737      * @return all variables in a loaded model
738      */
739     public String[] getAllDeclaredTypes() throws FMILException {
740         synchronized(syncObject) {
741
742             try {
743
744                 if(declaredTypes == null) {
745                         declaredTypes = getAllDeclaredTypes_(getModelIDNew());
746                 }
747                 return declaredTypes;
748
749             } catch (UnsatisfiedLinkError err) {
750                 throw new FMILException(UNSATISFIED_LINK);
751             } catch (Exception e) {
752                 throw new FMILException(e.getMessage());
753             }
754         }
755     }
756
757     private native String[] getAllDeclaredTypes_(int id);
758     
759     public String[] getAllDeclaredTypeDescriptions() throws FMILException {
760         synchronized(syncObject) {
761
762             try {
763
764                 if(declaredTypeDescriptions == null) {
765                         declaredTypeDescriptions = getAllDeclaredTypeDescriptions_(getModelIDNew());
766                 }
767                 return declaredTypeDescriptions;
768
769             } catch (UnsatisfiedLinkError err) {
770                 throw new FMILException(UNSATISFIED_LINK);
771             } catch (Exception e) {
772                 throw new FMILException(e.getMessage());
773             }
774         }
775     }
776
777     private native String[] getAllDeclaredTypeDescriptions_(int id);
778     
779     public String[] getAllDeclaredTypeQuantities() throws FMILException {
780         synchronized(syncObject) {
781
782             try {
783
784                 if(declaredTypeQuantities == null) {
785                         declaredTypeQuantities = getAllDeclaredTypeQuantities_(getModelIDNew());
786                 }
787                 return declaredTypeQuantities;
788
789             } catch (UnsatisfiedLinkError err) {
790                 throw new FMILException(UNSATISFIED_LINK);
791             } catch (Exception e) {
792                 throw new FMILException(e.getMessage());
793             }
794         }
795     }
796
797     private native String[] getAllDeclaredTypeQuantities_(int id);
798
799     public String[] getAllDeclaredTypeUnits() throws FMILException {
800         synchronized(syncObject) {
801
802             try {
803
804                 if(declaredTypeUnits == null) {
805                         declaredTypeUnits = getAllDeclaredTypeUnits_(getModelIDNew());
806                 }
807                 return declaredTypeUnits;
808
809             } catch (UnsatisfiedLinkError err) {
810                 throw new FMILException(UNSATISFIED_LINK);
811             } catch (Exception e) {
812                 throw new FMILException(e.getMessage());
813             }
814         }
815     }
816
817     private native String[] getAllDeclaredTypeUnits_(int id);
818     
819     
820 //
821 //    /**
822 //     * Get all variables from model that match the filter (and time variable)
823 //     * 
824 //     * @param regexp Regular expression filter
825 //     * @return An array of variable names that match regexp filter (and time-variable)
826 //     * @throws FMILException
827 //     */
828 //    public String[] filterVariables(String regexp) throws FMILException {       
829 //        synchronized(syncObject) {
830 //            try {
831 //
832 //                return filterVariables_(getModelID(), regexp + "|time");
833 //
834 //            } catch (UnsatisfiedLinkError err) {
835 //                throw new FMILException(UNSATISFIED_LINK);
836 //            } catch (Exception e) {
837 //                throw new FMILException(e.getMessage());
838 //            }
839 //        }
840 //    }
841 //
842 //    private native String[] filterVariables_(String id, String regexp);
843 ////
844 //    /**
845 //     * Get the last error message
846 //     * @return Last error message
847 //     */
848 //    public String getLastErrorMessage() throws FMILException {
849 //        synchronized(syncObject) {
850 //
851 //            try {
852 //
853 //              return "err";
854 //                //return getLastErrorMessage_(getModelID());
855 //
856 //            } catch (UnsatisfiedLinkError err) {
857 //                throw new FMILException(UNSATISFIED_LINK);
858 //            } catch (Exception e) {
859 //                throw new FMILException(e.getMessage());
860 //            }
861 //        }
862 //    }
863 //
864 //    private native String getLastErrorMessage_(String id);
865
866     /**
867      * Get a real (double) value for variable
868      * @param name Name of the variable
869      * @return value
870      * @throws FMILException
871      */
872     public double getRealValue(String name) throws FMILException {
873         synchronized(syncObject) {
874
875             try {
876                 // TODO: printtaa id ja name, jotta saadaan virheessä kiinni
877                 double result = getRealValue_(getModelIDNew(), variableMap.get(name));
878                 System.err.println("getRealValue " + name + " = " + result);
879                 return  result;
880             } catch (UnsatisfiedLinkError err) {
881                 throw new FMILException(UNSATISFIED_LINK);
882             } catch (Exception e) {
883                 throw new FMILException(e.getMessage());
884             }
885         }
886     }
887
888     private native double getRealValue_(int id, int variableReference);
889
890 //    /**
891 //     * Get a string value for variable
892 //     * @param name Name of the variable
893 //     * @return value
894 //     * @throws FMILException
895 //     */
896 //    public String getStringValue(String name) throws FMILException {
897 //        synchronized(syncObject) {
898 //
899 //            try {
900 //                return getStringValue_(getModelID(), name); 
901 //            } catch (UnsatisfiedLinkError err) {
902 //                throw new FMILException(UNSATISFIED_LINK);
903 //            } catch (Exception e) {
904 //                throw new FMILException(e.getMessage());
905 //            }
906 //        }
907 //    }
908 //
909 //    private native String getStringValue_(String id, String name);
910 //
911 //    /**
912 //     * Get an integer value for variable
913 //     * @param name Name of the variable
914 //     * @return value
915 //     * @throws FMILException
916 //     */
917 //    public int getIntegerValue(String name) throws FMILException {
918 //        synchronized(syncObject) {
919 //
920 //            try {
921 //                return getIntegerValue_(getModelID(), name); 
922 //            } catch (UnsatisfiedLinkError err) {
923 //                throw new FMILException(UNSATISFIED_LINK);
924 //            } catch (Exception e) {
925 //                throw new FMILException(e.getMessage());
926 //            }
927 //        }
928 //    }
929 //
930 //    private native int getIntegerValue_(String id, String name);
931 //
932 //    /**
933 //     * Get a real (double) value for variable
934 //     * @param name Name of the variable
935 //     * @return value
936 //     * @throws FMILException
937 //     */
938 //    public boolean getBooleanValue(String name) throws FMILException {
939 //        synchronized(syncObject) {
940 //
941 //            try {
942 //                return getBooleanValue_(getModelID(), name); 
943 //            } catch (UnsatisfiedLinkError err) {
944 //                throw new FMILException(UNSATISFIED_LINK);
945 //            } catch (Exception e) {
946 //                throw new FMILException(e.getMessage());
947 //            }
948 //        }
949 //    }
950 //
951 //    private native boolean getBooleanValue_(String id, String name);
952
953     private FileChannel channel; 
954     private FileLock lock;
955
956     @SuppressWarnings("resource")
957     private boolean lockFMUDirectory() {
958
959         try {
960             // Get a file channel for the lock file
961             File lockFile = new File(TEMP_FMU_DIRECTORY, LOCK_FILE_NAME);
962             if(!lockFile.isFile())
963                 lockFile.createNewFile();
964
965             channel = new RandomAccessFile(lockFile, "rw").getChannel();
966
967             // Use the file channel to create a lock on the file.
968             // This method blocks until it can retrieve the lock.
969             lock = channel.lock();
970
971             //          // Try acquiring the lock without blocking. This method returns
972             //          // null or throws an exception if the file is already locked.
973             //          try {
974             //              lock = channel.tryLock();
975             //          } catch (OverlappingFileLockException e) {
976             //              // File is already locked in this thread or virtual machine
977             //          }
978         } catch (IOException e) {
979             return false;
980         }
981
982         return true;
983     }
984
985     private boolean unlockFMUDirectory() {
986         try {
987             // Release the lock
988             if(lock != null)
989                 lock.release();
990
991             // Close the file
992             if(channel != null)
993                 channel.close();
994         } catch (IOException e) {
995             return false;
996         }
997         return true;
998     }
999
1000     private boolean removeFMUDirectoryContents() {
1001         // Remove contents
1002         try {
1003             File tempDir = new File(TEMP_FMU_DIRECTORY);
1004             FileUtils.deleteAll(tempDir);
1005             tempDir.delete();
1006         } catch (IOException e) {
1007             return false;
1008         }
1009         return true;
1010     }
1011     
1012     @Override
1013     protected void finalize() throws Throwable {
1014         try {
1015             unloadFMU();
1016         } catch (Throwable t) {
1017             LOGGER.error("Could not unload native FMU!", t);
1018         } finally {
1019             super.finalize();
1020         }
1021     }
1022 }