/******************************************************************************* * Copyright (c) 2007, 2010 Association for Decentralized Information Management * in Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.excel; import java.io.File; import java.io.IOException; import java.io.PrintStream; import java.net.URL; import java.net.URLDecoder; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Enumeration; import java.util.UUID; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.simantics.excel.ExecEnvironment.ARCHType; import org.simantics.excel.ExecEnvironment.OSType; import org.simantics.utils.FileUtils; public class Excel { private static Excel instance; public static Excel getInstance() throws ExcelException { return getInstance(System.out); } public static Excel getInstance(PrintStream out) throws ExcelException { if(instance == null) { if (Platform.inDevelopmentMode()) { Bundle b = Activator.getDefault().getBundle(); URL url = FileLocator.find(b, new Path(""), null); try { extractDir = new File(URLDecoder.decode(FileLocator.toFileURL(url).getPath(), "UTF-8")); } catch (IOException e) { e.printStackTrace(out); throw new ExcelException(e); } } else { try { start(out); } catch (IOException e) { e.printStackTrace(out); throw new ExcelException(e); } catch (Throwable t) { t.printStackTrace(out); throw new ExcelException(t); } } instance = new Excel(out); } return instance; } public File getDirectory() throws IOException { Bundle b = Platform.getBundle(Activator.PLUGIN_ID); if (b == null) throw new AssertionError("Could not resolve bundle '" + Activator.PLUGIN_ID + "' although were running in its fragment. Should not happen."); BundleContext context = b.getBundleContext(); if (context == null) throw new AssertionError("Could not get bundle context for bundle '" + Activator.PLUGIN_ID + "'. Bundle state is " + b.getState() + "."); File extractDir = context.getDataFile(""); if (extractDir == null) throw new IOException("Bundle '" + Activator.PLUGIN_ID + " context has no file system support. Cannot extract DLLs."); if (!extractDir.exists()) if (!extractDir.mkdir()) throw new IOException("Could not create directory '" + extractDir.getCanonicalPath() + "' for communicating with Excel."); return extractDir; } public String getContainer() { return UUID.randomUUID().toString(); } public String getFile(String name) { try { return getDirectory().getAbsolutePath() + "\\" + name; } catch (IOException e) { e.printStackTrace(); return null; } } private Excel(PrintStream out) throws ExcelException { try { Future future = init_(extractDir + File.separator); future.get(10, TimeUnit.SECONDS); } catch (InterruptedException e) { throw new ExcelException(e); } catch (ExecutionException e) { throw new ExcelException(e); } catch (TimeoutException e) { throw new ExcelException(e); } } public static IPath getAbsolutePath(String inBundle, String fullpath) { Bundle b = Platform.getBundle(inBundle); if (b == null) return null; return getAbsolutePath(b, fullpath); } public static IPath getAbsolutePath(Bundle inBundle, String fullpath) { // System.out.println("getAbsolutePath: " + inBundle + ", " + fullpath); IPath path = new Path(fullpath); URL u = FileLocator.find(inBundle, path, null); if (u != null) { try { u = FileLocator.resolve(u); // System.out.println(" PROTOCOL: " + u.getProtocol()); // System.out.println(" FILE: " + u.getFile()); // an absolute path is only available for the file protocol. if ("file".equals(u.getProtocol())) { IPath p = new Path(new File(u.getFile()).getAbsolutePath()); return p; } } catch (Exception e) { } } return null; } private static final Charset ascii = Charset.forName("US-ASCII"); private static final String REQUIRED_FILES_DESCRIPTOR_FILE = "required_files.txt"; /** * List here all the files that are required from this bundle to be able to * run the ProCoreServer executable. This is necessary for the starter core * below to be able to extract all the needed files incase the bundle * happens to be deployed as a JAR. */ private static final String[] DEFAULT_REQUIRED_FILES = { "SimanticsExcel.dll", "SimanticsExcel_64.dll" }; /** * The extraction directory is stored as a static field so that it can be * used to check whether the files have already been extracted. */ static private File extractDir = null; static private String[] requiredFiles = null; static private boolean needExtraction = false; private static IPath getAbsolutePath(String fullpath) { Bundle b = Platform.getBundle(Activator.PLUGIN_ID); if (b == null) return null; // System.out.println("getAbsolutePath: " + inBundle + ", " + fullpath); IPath path = new Path(fullpath); URL u = FileLocator.find(b, path, null); if (u != null) { try { u = FileLocator.resolve(u); // System.out.println(" PROTOCOL: " + u.getProtocol()); // System.out.println(" FILE: " + u.getFile()); // an absolute path is only available for the file protocol. if ("file".equals(u.getProtocol())) { IPath p = new Path(new File(u.getFile()).getAbsolutePath()); return p; } } catch (Exception e) { } } return null; } static String[] getRequiredFiles() { if (requiredFiles != null) return requiredFiles; Bundle b = Platform.getBundle(Activator.PLUGIN_ID); if (b == null) return null; ArrayList> enu = new ArrayList>(); enu.add(b.findEntries("/", "*.dll", true)); //enu.add(b.findEntries("/", "*.manifest", true)); ArrayList filez = new ArrayList(); for(Enumeration e : enu) { while(e.hasMoreElements()) { URL url = (URL)e.nextElement(); filez.add(url.getFile()); // System.out.println(url.getFile()); } } requiredFiles = filez.toArray(new String[filez.size()]); return requiredFiles; } private static File extractFiles() throws IOException { Bundle b = Platform.getBundle(Activator.PLUGIN_ID); if (b == null) throw new AssertionError("Could not resolve bundle '" + Activator.PLUGIN_ID + "' although were running in it. Should not happen."); //System.out.println("bundle dir: " + baseDir); for (String file : getRequiredFiles()) { // FileLocator find files in fragments also, Bundle.getEntry won't do that. URL url = FileLocator.find(b, new Path(file), null); File fzz = new File(extractDir, file); Path path = new Path(fzz.getAbsolutePath()); path.removeLastSegments(1).toFile().mkdirs(); FileUtils.copyResource(url, fzz, false); } return extractDir; } public static final String EXCEL_FOLDER = "Excel"; //$NON-NLS-1$ public static void start(PrintStream out) throws IOException { Bundle b = Platform.getBundle(Activator.PLUGIN_ID); if (b == null) throw new AssertionError("Could not resolve bundle '" + Activator.PLUGIN_ID + "' although were running in its fragment. Should not happen."); BundleContext context = b.getBundleContext(); if (context == null) throw new AssertionError("Could not get bundle context for bundle '" + Activator.PLUGIN_ID + "'. Bundle state is " + b.getState() + "."); IWorkspace workspace = ResourcesPlugin.getWorkspace(); IWorkspaceRoot workspaceRoot = workspace.getRoot(); extractDir = new File(workspaceRoot.getLocation().toFile(), EXCEL_FOLDER); if (!extractDir.exists()) if (!extractDir.mkdir()) throw new IOException("Could not create directory '" + extractDir.getCanonicalPath() + "' for communicating with Excel."); String asd = ""; ExecEnvironment env = ExecEnvironment.calculate(); if (env.os == OSType.WINDOWS) { if (env.arch == ARCHType.X86) { asd = extractDir + "\\SimanticsExcel.dll"; } else if (env.arch == ARCHType.X86_64) { asd = extractDir + "\\SimanticsExcel_64.dll"; } } File test = new File(asd); if(test.exists()) { needExtraction = false; return; } else { needExtraction = true; } // Resolve executable location if (needExtraction) { extractDir = extractFiles(); } else { out.println("needExtraction=false"); } } // Initialization private native int init(); private native String open(String fileName, String sheetName); private native String getModifications(int handle); private native int setDouble(int handle, int row, int column, double value); private native int setString(int handle, int row, int column, String value); private native int setName(int handle, int row, int column, String value); private native int setVisible(int handle, boolean value); private native int close(int handle); private native double getDouble(int handle, int row, int column); private native String getString(int handle, int row, int column); final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); public Future init_(final String path) { return scheduler.submit(new Runnable() { @Override public void run() { String asd = ""; ExecEnvironment env = ExecEnvironment.calculate(); if (env.os == OSType.WINDOWS) { if (env.arch == ARCHType.X86) { asd = extractDir + "\\SimanticsExcel.dll"; } else if (env.arch == ARCHType.X86_64) { asd = extractDir + "\\SimanticsExcel_64.dll"; } } System.load(asd); init(); } }); } public int open2_(final String fileName, final String sheetName) { try { return scheduler.submit(new Callable() { @Override public Integer call() throws Exception { return Integer.parseInt(open(fileName, sheetName)); } }).get(); } catch (Exception e) { e.printStackTrace(); return -1; } } public String open_(final String fileName, final String sheetName) { try { return scheduler.submit(new Callable() { @Override public String call() throws Exception { return open(fileName, sheetName); } }).get(); } catch (Exception e) { e.printStackTrace(); return ""; } } public int setDouble_(final int handle, final int row, final int column, final double value) { try { return scheduler.submit(new Callable() { @Override public Integer call() throws Exception { // System.out.println("Excel: setDouble at " + row + "-" + column); return setDouble(handle, row, column, value); } }).get(); } catch (Exception e) { e.printStackTrace(); return -1; } } public int setString_(final int handle, final int row, final int column, final String value) { try { return scheduler.submit(new Callable() { @Override public Integer call() throws Exception { // System.out.println("Excel: setString at " + row + "-" + column); return setString(handle, row, column, value); } }).get(); } catch (Exception e) { e.printStackTrace(); return -1; } } public String getModifications_(final int handle) { try { return scheduler.submit(new Callable() { @Override public String call() throws Exception { // System.out.println("Excel: setString at " + row + "-" + column); return getModifications(handle); } }).get(); } catch (Exception e) { e.printStackTrace(); return ""; } } public int setName_(final int handle, final int row, final int column, final String value) { try { return scheduler.submit(new Callable() { @Override public Integer call() throws Exception { // System.out.println("Excel: setString at " + row + "-" + column); return setName(handle, row, column, value); } }).get(); } catch (Exception e) { e.printStackTrace(); return -1; } } public int setVisible_(final int handle, final Boolean value) { try { return scheduler.submit(new Callable() { @Override public Integer call() throws Exception { // System.out.println("Excel: setString at " + row + "-" + column); return setVisible(handle, value); } }).get(); } catch (Exception e) { e.printStackTrace(); return -1; } } public int close_(final int handle) { try { return scheduler.submit(new Callable() { @Override public Integer call() throws Exception { // System.out.println("Excel: close " + handle); int ret = close(handle); // System.out.println("Excel: close = " + ret); return ret; } }).get(); } catch (Exception e) { e.printStackTrace(); return -1; } } public double getDouble_(final int handle, final int row, final int column) { try { return scheduler.submit(new Callable() { @Override public Double call() throws Exception { return getDouble(handle, row, column); } }).get(); } catch (Exception e) { e.printStackTrace(); return Double.NaN; } } public String getString_(final int handle, final int row, final int column) { try { return scheduler.submit(new Callable() { @Override public String call() throws Exception { return getString(handle, row, column); } }).get(); } catch (Exception e) { e.printStackTrace(); return null; } } }