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
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.excel;
\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
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
44 public class Excel {
\r
46 private static Excel instance;
\r
48 public static Excel getInstance(PrintStream out) throws ExcelException {
\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
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
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
72 instance = new Excel(out);
\r
80 public File getDirectory() throws IOException {
\r
82 Bundle b = Platform.getBundle(Activator.PLUGIN_ID);
\r
84 throw new AssertionError("Could not resolve bundle '" + Activator.PLUGIN_ID + "' although were running in its fragment. Should not happen.");
\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
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
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
102 public String getContainer() {
\r
103 return UUID.randomUUID().toString();
\r
106 public String getFile(String name) {
\r
108 return getDirectory().getAbsolutePath() + "\\" + name;
\r
109 } catch (IOException e) {
\r
110 e.printStackTrace();
\r
115 private Excel(PrintStream out) throws ExcelException {
\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
130 public static IPath getAbsolutePath(String inBundle, String fullpath) {
\r
131 Bundle b = Platform.getBundle(inBundle);
\r
134 return getAbsolutePath(b, fullpath);
\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
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
151 } catch (Exception e) {
\r
157 private static final Charset ascii = Charset.forName("US-ASCII");
\r
159 private static final String REQUIRED_FILES_DESCRIPTOR_FILE = "required_files.txt";
\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
167 private static final String[] DEFAULT_REQUIRED_FILES = {
\r
168 "SimanticsExcel.dll", "SimanticsExcel_64.dll"
\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
175 static private File extractDir = null;
\r
177 static private String[] requiredFiles = null;
\r
179 static private boolean needExtraction = false;
\r
181 private static IPath getAbsolutePath(String fullpath) {
\r
182 Bundle b = Platform.getBundle(Activator.PLUGIN_ID);
\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
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
198 } catch (Exception e) {
\r
204 static String[] getRequiredFiles() {
\r
206 if (requiredFiles != null)
\r
207 return requiredFiles;
\r
209 Bundle b = Platform.getBundle(Activator.PLUGIN_ID);
\r
213 ArrayList<Enumeration<?>> enu = new ArrayList<Enumeration<?>>();
\r
215 enu.add(b.findEntries("/", "*.dll", true));
\r
216 //enu.add(b.findEntries("/", "*.manifest", true));
\r
218 ArrayList<String> filez = new ArrayList<String>();
\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
228 requiredFiles = filez.toArray(new String[filez.size()]);
\r
230 return requiredFiles;
\r
234 private static File extractFiles() throws IOException {
\r
235 Bundle b = Platform.getBundle(Activator.PLUGIN_ID);
\r
237 throw new AssertionError("Could not resolve bundle '" + Activator.PLUGIN_ID + "' although were running in it. Should not happen.");
\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
251 public static final String EXCEL_FOLDER = "Excel"; //$NON-NLS-1$
\r
253 public static void start(PrintStream out) throws IOException {
\r
255 Bundle b = Platform.getBundle(Activator.PLUGIN_ID);
\r
257 throw new AssertionError("Could not resolve bundle '" + Activator.PLUGIN_ID + "' although were running in its fragment. Should not happen.");
\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
263 IWorkspace workspace = ResourcesPlugin.getWorkspace();
\r
264 IWorkspaceRoot workspaceRoot = workspace.getRoot();
\r
265 extractDir = new File(workspaceRoot.getLocation().toFile(), EXCEL_FOLDER);
\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
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
282 File test = new File(asd);
\r
283 if(test.exists()) {
\r
284 needExtraction = false;
\r
287 needExtraction = true;
\r
290 // Resolve executable location
\r
291 if (needExtraction) {
\r
292 extractDir = extractFiles();
\r
294 out.println("needExtraction=false");
\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
309 // private native double getDouble(int handle, int row, int column);
\r
310 // private native String getString(int handle, int row, int column);
\r
312 final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
\r
314 public Future<?> init_(final String path) {
\r
315 return scheduler.submit(new Runnable() {
\r
317 public void run() {
\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
334 public String open_(final String fileName, final String sheetName) {
\r
336 return scheduler.submit(new Callable<String>() {
\r
338 public String call() throws Exception {
\r
339 return open(fileName, sheetName);
\r
342 } catch (Exception e) {
\r
343 e.printStackTrace();
\r
348 public int setDouble_(final int handle, final int row, final int column, final double value) {
\r
350 return scheduler.submit(new Callable<Integer>() {
\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
357 } catch (Exception e) {
\r
358 e.printStackTrace();
\r
363 public int setString_(final int handle, final int row, final int column, final String value) {
\r
365 return scheduler.submit(new Callable<Integer>() {
\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
372 } catch (Exception e) {
\r
373 e.printStackTrace();
\r
378 public String getModifications_(final int handle) {
\r
380 return scheduler.submit(new Callable<String>() {
\r
382 public String call() throws Exception {
\r
383 // System.out.println("Excel: setString at " + row + "-" + column);
\r
384 return getModifications(handle);
\r
387 } catch (Exception e) {
\r
388 e.printStackTrace();
\r
393 public int setName_(final int handle, final int row, final int column, final String value) {
\r
395 return scheduler.submit(new Callable<Integer>() {
\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
402 } catch (Exception e) {
\r
403 e.printStackTrace();
\r
408 public int setVisible_(final int handle, final Boolean value) {
\r
410 return scheduler.submit(new Callable<Integer>() {
\r
412 public Integer call() throws Exception {
\r
413 // System.out.println("Excel: setString at " + row + "-" + column);
\r
414 return setVisible(handle, value);
\r
417 } catch (Exception e) {
\r
418 e.printStackTrace();
\r
423 public int close_(final int handle) {
\r
425 return scheduler.submit(new Callable<Integer>() {
\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
434 } catch (Exception e) {
\r
435 e.printStackTrace();
\r
440 // public double getDouble_(final int handle, final int row, final int column) {
\r
442 // return scheduler.submit(new Callable<Double>() {
\r
444 // public Double call() throws Exception {
\r
445 // return getDouble(handle, row, column);
\r
448 // } catch (Exception e) {
\r
449 // e.printStackTrace();
\r
450 // return Double.NaN;
\r
454 // public String getString_(final int handle, final int row, final int column) {
\r
456 // return scheduler.submit(new Callable<String>() {
\r
458 // public String call() throws Exception {
\r
459 // return getString(handle, row, column);
\r
462 // } catch (Exception e) {
\r
463 // e.printStackTrace();
\r