]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.excel/src/org/simantics/excel/Excel.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.excel / src / org / simantics / excel / Excel.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.excel;\r
13 \r
14 import java.io.File;\r
15 import java.io.IOException;\r
16 import java.io.PrintStream;\r
17 import java.net.URL;\r
18 import java.net.URLDecoder;\r
19 import java.nio.charset.Charset;\r
20 import java.util.ArrayList;\r
21 import java.util.Enumeration;\r
22 import java.util.UUID;\r
23 import java.util.concurrent.Callable;\r
24 import java.util.concurrent.ExecutionException;\r
25 import java.util.concurrent.Executors;\r
26 import java.util.concurrent.Future;\r
27 import java.util.concurrent.ScheduledExecutorService;\r
28 import java.util.concurrent.TimeUnit;\r
29 import java.util.concurrent.TimeoutException;\r
30 \r
31 import org.eclipse.core.resources.IWorkspace;\r
32 import org.eclipse.core.resources.IWorkspaceRoot;\r
33 import org.eclipse.core.resources.ResourcesPlugin;\r
34 import org.eclipse.core.runtime.FileLocator;\r
35 import org.eclipse.core.runtime.IPath;\r
36 import org.eclipse.core.runtime.Path;\r
37 import org.eclipse.core.runtime.Platform;\r
38 import org.osgi.framework.Bundle;\r
39 import org.osgi.framework.BundleContext;\r
40 import org.simantics.excel.ExecEnvironment.ARCHType;\r
41 import org.simantics.excel.ExecEnvironment.OSType;\r
42 import org.simantics.utils.FileUtils;\r
43 \r
44 public class Excel {\r
45 \r
46     private static Excel instance;\r
47 \r
48     public static Excel getInstance(PrintStream out) throws ExcelException {\r
49 \r
50         if(instance == null) {\r
51                 if (Platform.inDevelopmentMode()) {\r
52                 Bundle b = Activator.getDefault().getBundle();\r
53                 URL url = FileLocator.find(b, new Path(""), null);\r
54                 try {\r
55                     extractDir = new File(URLDecoder.decode(FileLocator.toFileURL(url).getPath(), "UTF-8"));\r
56                 } catch (IOException e) {\r
57                     e.printStackTrace(out);\r
58                     throw new ExcelException(e);\r
59                 }\r
60             } else {\r
61                 try {\r
62                     start(out);\r
63                 } catch (IOException e) {\r
64                     e.printStackTrace(out);\r
65                     throw new ExcelException(e);\r
66                 } catch (Throwable t) {\r
67                     t.printStackTrace(out);\r
68                     throw new ExcelException(t);\r
69                 }\r
70             }\r
71 \r
72                 instance = new Excel(out);\r
73             \r
74         }\r
75 \r
76         return instance;\r
77 \r
78     }\r
79 \r
80     public File getDirectory() throws IOException {\r
81 \r
82         Bundle b = Platform.getBundle(Activator.PLUGIN_ID);\r
83         if (b == null)\r
84             throw new AssertionError("Could not resolve bundle '" + Activator.PLUGIN_ID + "' although were running in its fragment. Should not happen.");\r
85 \r
86         BundleContext context = b.getBundleContext();\r
87         if (context == null)\r
88             throw new AssertionError("Could not get bundle context for bundle '" + Activator.PLUGIN_ID + "'. Bundle state is " + b.getState() + ".");\r
89 \r
90         File extractDir = context.getDataFile("");\r
91         if (extractDir == null)\r
92             throw new IOException("Bundle '" + Activator.PLUGIN_ID + " context has no file system support. Cannot extract server executables.");\r
93 \r
94         if (!extractDir.exists())\r
95             if (!extractDir.mkdir())\r
96                 throw new IOException("Could not create directory '" + extractDir.getCanonicalPath() + "' for storing Balas solver data.");\r
97         \r
98         return extractDir;\r
99         \r
100     }\r
101     \r
102     public String getContainer() {\r
103         return UUID.randomUUID().toString();\r
104     }\r
105     \r
106     public String getFile(String name) {\r
107         try {\r
108             return getDirectory().getAbsolutePath() + "\\" + name;\r
109         } catch (IOException e) {\r
110             e.printStackTrace();\r
111             return null;\r
112         }\r
113     }\r
114     \r
115     private Excel(PrintStream out) throws ExcelException {\r
116 \r
117         try {\r
118                 Future<?> future = init_(extractDir + File.separator);\r
119                         future.get(10, TimeUnit.SECONDS);\r
120                 } catch (InterruptedException e) {\r
121                         throw new ExcelException(e);\r
122                 } catch (ExecutionException e) {\r
123                         throw new ExcelException(e);\r
124                 } catch (TimeoutException e) {\r
125                         throw new ExcelException(e);\r
126                 }\r
127 \r
128     }\r
129 \r
130     public static IPath getAbsolutePath(String inBundle, String fullpath) {\r
131         Bundle b = Platform.getBundle(inBundle);\r
132         if (b == null)\r
133             return null;\r
134         return getAbsolutePath(b, fullpath);\r
135     }\r
136 \r
137     public static IPath getAbsolutePath(Bundle inBundle, String fullpath) {\r
138 //      System.out.println("getAbsolutePath: " + inBundle + ", " + fullpath);\r
139         IPath path = new Path(fullpath);\r
140         URL u = FileLocator.find(inBundle, path, null);\r
141         if (u != null) {\r
142             try {\r
143                 u = FileLocator.resolve(u);\r
144 //              System.out.println("  PROTOCOL: " + u.getProtocol());\r
145 //              System.out.println("  FILE: " + u.getFile());\r
146                 // an absolute path is only available for the file protocol.\r
147                 if ("file".equals(u.getProtocol())) {\r
148                     IPath p = new Path(new File(u.getFile()).getAbsolutePath());\r
149                     return p;\r
150                 }\r
151             } catch (Exception e) {\r
152             }\r
153         }\r
154         return null;\r
155     }\r
156 \r
157     private static final Charset  ascii             = Charset.forName("US-ASCII");\r
158 \r
159     private static final String   REQUIRED_FILES_DESCRIPTOR_FILE = "required_files.txt";\r
160 \r
161     /**\r
162      * List here all the files that are required from this bundle to be able to\r
163      * run the ProCoreServer executable. This is necessary for the starter core\r
164      * below to be able to extract all the needed files incase the bundle\r
165      * happens to be deployed as a JAR.\r
166      */\r
167     private static final String[] DEFAULT_REQUIRED_FILES    = {\r
168         "SimanticsExcel.dll", "SimanticsExcel_64.dll"\r
169     };\r
170 \r
171     /**\r
172      * The extraction directory is stored as a static field so that it can be\r
173      * used to check whether the files have already been extracted.\r
174      */\r
175     static private  File           extractDir        = null;\r
176 \r
177     static private String[]              requiredFiles     = null;\r
178 \r
179     static private boolean               needExtraction    = false;\r
180 \r
181     private static IPath getAbsolutePath(String fullpath) {\r
182         Bundle b = Platform.getBundle(Activator.PLUGIN_ID);\r
183         if (b == null)\r
184             return null;\r
185 //      System.out.println("getAbsolutePath: " + inBundle + ", " + fullpath);\r
186         IPath path = new Path(fullpath);\r
187         URL u = FileLocator.find(b, path, null);\r
188         if (u != null) {\r
189             try {\r
190                 u = FileLocator.resolve(u);\r
191 //              System.out.println("  PROTOCOL: " + u.getProtocol());\r
192 //              System.out.println("  FILE: " + u.getFile());\r
193                 // an absolute path is only available for the file protocol.\r
194                 if ("file".equals(u.getProtocol())) {\r
195                     IPath p = new Path(new File(u.getFile()).getAbsolutePath());\r
196                     return p;\r
197                 }\r
198             } catch (Exception e) {\r
199             }\r
200         }\r
201         return null;\r
202     }\r
203 \r
204     static String[] getRequiredFiles() {\r
205 \r
206         if (requiredFiles != null)\r
207             return requiredFiles;\r
208 \r
209         Bundle b = Platform.getBundle(Activator.PLUGIN_ID);\r
210         if (b == null)\r
211             return null;\r
212 \r
213         ArrayList<Enumeration<?>> enu = new ArrayList<Enumeration<?>>();\r
214 \r
215         enu.add(b.findEntries("/", "*.dll", true));\r
216         //enu.add(b.findEntries("/", "*.manifest", true));\r
217 \r
218         ArrayList<String> filez = new ArrayList<String>();\r
219 \r
220         for(Enumeration<?> e : enu) {\r
221             while(e.hasMoreElements()) {\r
222                 URL url = (URL)e.nextElement();\r
223                 filez.add(url.getFile());\r
224 //                      System.out.println(url.getFile());\r
225             }\r
226         }\r
227 \r
228         requiredFiles = filez.toArray(new String[filez.size()]);\r
229 \r
230         return requiredFiles;\r
231 \r
232     }\r
233 \r
234     private static File extractFiles() throws IOException {\r
235         Bundle b = Platform.getBundle(Activator.PLUGIN_ID);\r
236         if (b == null)\r
237             throw new AssertionError("Could not resolve bundle '" + Activator.PLUGIN_ID + "' although were running in it. Should not happen.");\r
238 \r
239         //System.out.println("bundle dir: " + baseDir);\r
240         for (String file : getRequiredFiles()) {\r
241             // FileLocator find files in fragments also, Bundle.getEntry won't do that.\r
242             URL url = FileLocator.find(b, new Path(file), null);\r
243             File fzz = new File(extractDir, file);\r
244             Path path = new Path(fzz.getAbsolutePath());\r
245             path.removeLastSegments(1).toFile().mkdirs();\r
246             FileUtils.copyResource(url, fzz, false);\r
247         }\r
248         return extractDir;\r
249     }\r
250 \r
251     public static final String EXCEL_FOLDER = "Excel"; //$NON-NLS-1$\r
252     \r
253     public static void start(PrintStream out) throws IOException {\r
254 \r
255         Bundle b = Platform.getBundle(Activator.PLUGIN_ID);\r
256         if (b == null)\r
257             throw new AssertionError("Could not resolve bundle '" + Activator.PLUGIN_ID + "' although were running in its fragment. Should not happen.");\r
258 \r
259         BundleContext context = b.getBundleContext();\r
260         if (context == null)\r
261             throw new AssertionError("Could not get bundle context for bundle '" + Activator.PLUGIN_ID + "'. Bundle state is " + b.getState() + ".");\r
262 \r
263         IWorkspace workspace = ResourcesPlugin.getWorkspace();\r
264         IWorkspaceRoot workspaceRoot = workspace.getRoot();\r
265         extractDir = new File(workspaceRoot.getLocation().toFile(), EXCEL_FOLDER);\r
266         \r
267         if (!extractDir.exists())\r
268             if (!extractDir.mkdir())\r
269                 throw new IOException("Could not create directory '" + extractDir.getCanonicalPath() + "' for storing Balas solver data.");\r
270 \r
271         String asd = "";\r
272         ExecEnvironment env = ExecEnvironment.calculate();\r
273         if (env.os == OSType.WINDOWS) {\r
274             if (env.arch == ARCHType.X86) {\r
275                 asd = extractDir + "\\SimanticsExcel.dll";\r
276             } else if (env.arch == ARCHType.X86_64) {\r
277                 asd = extractDir + "\\SimanticsExcel_64.dll";\r
278             }\r
279         }\r
280 \r
281         \r
282         File test = new File(asd);\r
283         if(test.exists()) {\r
284             needExtraction = false;\r
285             return;\r
286         } else {\r
287             needExtraction = true;\r
288         }\r
289 \r
290         // Resolve executable location\r
291         if (needExtraction) {\r
292             extractDir = extractFiles();\r
293         } else {\r
294             out.println("needExtraction=false");\r
295         }\r
296 \r
297     }\r
298 \r
299     // Initialization\r
300     private native int init();\r
301     private native String open(String fileName, String sheetName);\r
302     private native String getModifications(int handle);\r
303     private native int setDouble(int handle, int row, int column, double value);\r
304     private native int setString(int handle, int row, int column, String value);\r
305     private native int setName(int handle, int row, int column, String value);\r
306     private native int setVisible(int handle, boolean value);\r
307     private native int close(int handle);\r
308     \r
309 //    private native double getDouble(int handle, int row, int column);\r
310 //    private native String getString(int handle, int row, int column);\r
311 \r
312     final ScheduledExecutorService  scheduler = Executors.newSingleThreadScheduledExecutor();\r
313 \r
314     public Future<?> init_(final String path) {\r
315         return scheduler.submit(new Runnable() {\r
316                 @Override\r
317                 public void run() {\r
318 \r
319                     String asd = "";\r
320                 ExecEnvironment env = ExecEnvironment.calculate();\r
321                 if (env.os == OSType.WINDOWS) {\r
322                     if (env.arch == ARCHType.X86) {\r
323                         asd = extractDir + "\\SimanticsExcel.dll";\r
324                     } else if (env.arch == ARCHType.X86_64) {\r
325                         asd = extractDir + "\\SimanticsExcel_64.dll";\r
326                     }\r
327                 }\r
328                 System.load(asd);\r
329                 init();\r
330                 }\r
331         });\r
332     }\r
333 \r
334     public String open_(final String fileName, final String sheetName) {\r
335         try {\r
336             return scheduler.submit(new Callable<String>() {\r
337                 @Override\r
338                 public String call() throws Exception {\r
339                     return open(fileName, sheetName);\r
340                 }\r
341             }).get();\r
342         } catch (Exception e) {\r
343             e.printStackTrace();\r
344             return "";\r
345         }\r
346     }\r
347 \r
348     public int setDouble_(final int handle, final int row, final int column, final double value) {\r
349         try {\r
350             return scheduler.submit(new Callable<Integer>() {\r
351                 @Override\r
352                 public Integer call() throws Exception {\r
353 //                    System.out.println("Excel: setDouble at " + row + "-" + column); \r
354                     return setDouble(handle, row, column, value);\r
355                 }\r
356             }).get();\r
357         } catch (Exception e) {\r
358             e.printStackTrace();\r
359             return -1;\r
360         }\r
361     }\r
362 \r
363     public int setString_(final int handle, final int row, final int column, final String value) {\r
364         try {\r
365             return scheduler.submit(new Callable<Integer>() {\r
366                 @Override\r
367                 public Integer call() throws Exception {\r
368 //                    System.out.println("Excel: setString at " + row + "-" + column); \r
369                     return setString(handle, row, column, value);\r
370                 }\r
371             }).get();\r
372         } catch (Exception e) {\r
373             e.printStackTrace();\r
374             return -1;\r
375         }\r
376     }\r
377 \r
378     public String getModifications_(final int handle) {\r
379         try {\r
380             return scheduler.submit(new Callable<String>() {\r
381                 @Override\r
382                 public String call() throws Exception {\r
383 //                    System.out.println("Excel: setString at " + row + "-" + column); \r
384                     return getModifications(handle);\r
385                 }\r
386             }).get();\r
387         } catch (Exception e) {\r
388             e.printStackTrace();\r
389             return "";\r
390         }\r
391     }\r
392 \r
393     public int setName_(final int handle, final int row, final int column, final String value) {\r
394         try {\r
395             return scheduler.submit(new Callable<Integer>() {\r
396                 @Override\r
397                 public Integer call() throws Exception {\r
398 //                    System.out.println("Excel: setString at " + row + "-" + column); \r
399                     return setName(handle, row, column, value);\r
400                 }\r
401             }).get();\r
402         } catch (Exception e) {\r
403             e.printStackTrace();\r
404             return -1;\r
405         }\r
406     }\r
407 \r
408     public int setVisible_(final int handle, final Boolean value) {\r
409         try {\r
410             return scheduler.submit(new Callable<Integer>() {\r
411                 @Override\r
412                 public Integer call() throws Exception {\r
413 //                    System.out.println("Excel: setString at " + row + "-" + column); \r
414                     return setVisible(handle, value);\r
415                 }\r
416             }).get();\r
417         } catch (Exception e) {\r
418             e.printStackTrace();\r
419             return -1;\r
420         }\r
421     }\r
422 \r
423     public int close_(final int handle) {\r
424         try {\r
425             return scheduler.submit(new Callable<Integer>() {\r
426                 @Override\r
427                 public Integer call() throws Exception {\r
428 //                    System.out.println("Excel: close " + handle);\r
429                     int ret = close(handle); \r
430 //                    System.out.println("Excel: close = " + ret);\r
431                     return ret;\r
432                 }\r
433             }).get();\r
434         } catch (Exception e) {\r
435             e.printStackTrace();\r
436             return -1;\r
437         }\r
438     }\r
439     \r
440 //    public double getDouble_(final int handle, final int row, final int column) {\r
441 //        try {\r
442 //            return scheduler.submit(new Callable<Double>() {\r
443 //                @Override\r
444 //                public Double call() throws Exception {\r
445 //                    return getDouble(handle, row, column);\r
446 //                }\r
447 //            }).get();\r
448 //        } catch (Exception e) {\r
449 //            e.printStackTrace();\r
450 //            return Double.NaN;\r
451 //        }\r
452 //    }\r
453 //    \r
454 //    public String getString_(final int handle, final int row, final int column) {\r
455 //        try {\r
456 //            return scheduler.submit(new Callable<String>() {\r
457 //                @Override\r
458 //                public String call() throws Exception {\r
459 //                    return getString(handle, row, column);\r
460 //                }\r
461 //            }).get();\r
462 //        } catch (Exception e) {\r
463 //            e.printStackTrace();\r
464 //            return null;\r
465 //        }\r
466 //    }\r
467 \r
468 }\r