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