]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.db.procore.server.environment/src/org/simantics/db/procore/server/environment/windows/Msi.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.db.procore.server.environment / src / org / simantics / db / procore / server / environment / windows / Msi.java
diff --git a/bundles/org.simantics.db.procore.server.environment/src/org/simantics/db/procore/server/environment/windows/Msi.java b/bundles/org.simantics.db.procore.server.environment/src/org/simantics/db/procore/server/environment/windows/Msi.java
new file mode 100644 (file)
index 0000000..85c83a5
--- /dev/null
@@ -0,0 +1,245 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.db.procore.server.environment.windows;\r
+\r
+import java.io.Closeable;\r
+import java.io.File;\r
+import java.io.FileInputStream;\r
+import java.io.FileNotFoundException;\r
+import java.io.FileOutputStream;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.net.URL;\r
+import java.net.URLDecoder;\r
+import java.security.MessageDigest;\r
+import java.security.NoSuchAlgorithmException;\r
+import java.util.Arrays;\r
+\r
+import org.simantics.db.procore.server.environment.ExecutionEnvironment;\r
+import org.simantics.db.procore.server.environment.ExecutionEnvironmentException;\r
+\r
+/**\r
+ * Provides Java access to Windows Msi API functions:\r
+ * <ul>\r
+ * <li>{@link #MsiQueryProductState(String)} (see <a\r
+ * href="http://msdn.microsoft.com/en-us/library/aa370363(VS.85).aspx">MSDN</a>)</li>\r
+ * </ul>\r
+ * \r
+ * @author Tuukka Lehtonen\r
+ */\r
+public class Msi {\r
+\r
+    public static void checkOneOfProductsInstalled(Product... products) throws ExecutionEnvironmentException {\r
+        StringBuilder sb = new StringBuilder();\r
+        sb.append("None of the following products are installed properly:\n");\r
+        for (Product product : products) {\r
+            ProductState state = Msi.MsiQueryProductState(product.getCode());\r
+            switch (state) {\r
+                case DEFAULT:\r
+                    // One of the listed products is installed OK.\r
+                    return;\r
+                default:\r
+                    sb.append("\t" + product);\r
+                    sb.append(" - MsiQueryProductState returned ");\r
+                    sb.append(state);\r
+                    sb.append("\n");\r
+            }\r
+        }\r
+        throw new ExecutionEnvironmentException("Cannot run ProCore database server in this environment due to the following problems:\n" + sb.toString(), Arrays.asList(products));\r
+    }\r
+\r
+    public static void checkProductsInstalled(Product... products) throws ExecutionEnvironmentException {\r
+        StringBuilder sb = new StringBuilder();\r
+        for (Product product : products) {\r
+            ProductState state = Msi.MsiQueryProductState(product.getCode());\r
+            switch (state) {\r
+                case DEFAULT:\r
+                    // Installed OK\r
+                    continue;\r
+                default:\r
+                    sb.append("\tProduct " + product + " is not installed properly, MsiQueryProductState returned " + state);\r
+                    sb.append("\n");\r
+            }\r
+        }\r
+        if (sb.length() > 0) {\r
+            // Something is not installed right, throw exception\r
+            throw new ExecutionEnvironmentException("Cannot run ProCore database server in this environment due to the following problems:\n" + sb.toString(), Arrays.asList(products));\r
+        }\r
+    }\r
+\r
+    // -------------------------------------------------------------------------\r
+\r
+    public static ProductState MsiQueryProductState(String productCode) {\r
+        int result = MsiQueryProductState0(productCode);\r
+        return ProductState.of(result);\r
+    }\r
+\r
+    private static native int MsiQueryProductState0(String productCode);\r
+\r
+    // -------------------------------------------------------------------------\r
+\r
+    private static final String DLL_NAME = "msijni.dll";\r
+    private static final String DLL_NAME_64 = "msijni64.dll";\r
+\r
+    static {\r
+        initialize();\r
+    }\r
+\r
+    private static void initialize() {\r
+        ExecutionEnvironment env = ExecutionEnvironment.calculate();\r
+        String libName = null;\r
+        switch (env.arch) {\r
+            case X86:\r
+                libName = DLL_NAME;\r
+                break;\r
+            case X86_64:\r
+                libName = DLL_NAME_64;\r
+                break;\r
+            default:\r
+                return;\r
+        }\r
+\r
+        URL libURL = Msi.class.getResource("/" + libName);\r
+        if (libURL != null) {\r
+            try {\r
+                if ("file".equals(libURL.getProtocol())) {\r
+                    File path = new File(URLDecoder.decode(libURL.getPath(), "UTF-8"));\r
+                    initialize(path);\r
+                } else {\r
+                    File libFile = extractLib(libURL, libName);\r
+                    initialize(libFile);\r
+                }\r
+            } catch (IOException e) {\r
+                e.printStackTrace();\r
+            }\r
+        }\r
+    }\r
+\r
+    private static void initialize(File path) {\r
+        //System.out.println("load msijni: " + path);\r
+        System.load(path.toString());\r
+    }\r
+\r
+    /**\r
+     * Extracts the specified source file in the specified bundle into the\r
+     * specified local directory.\r
+     * \r
+     * @param url the source URL to stream the resource from\r
+     * @param targetFile the target file to write the resource to\r
+     * @param deleteOnExit <code>true</code> to use {@link File#deleteOnExit()}\r
+     *        on the resulting file. Note that this does not guarantee that the\r
+     *        file is deleted when the JVM exits\r
+     * @return the resulting file\r
+     * @throws FileNotFoundException\r
+     */\r
+    private static File copyResource(URL url, File targetFile) throws IOException, FileNotFoundException {\r
+        FileOutputStream os = null;\r
+        InputStream is = null;\r
+        try {\r
+            if (targetFile.exists())\r
+                targetFile.delete();\r
+\r
+            is = url.openStream();\r
+            int read;\r
+            byte [] buffer = new byte [16384];\r
+            os = new FileOutputStream (targetFile);\r
+            while ((read = is.read (buffer)) != -1) {\r
+                os.write(buffer, 0, read);\r
+            }\r
+            os.close ();\r
+            is.close ();\r
+\r
+            return targetFile;\r
+        } finally {\r
+            uncheckedClose(os);\r
+            uncheckedClose(is);\r
+        }\r
+    }\r
+\r
+\r
+    private static void uncheckedClose(Closeable closeable) {\r
+        try {\r
+            if (closeable != null)\r
+                closeable.close();\r
+        } catch (IOException e) {\r
+            //ignore\r
+        }\r
+    }\r
+\r
+    private static File extractLib(URL libURL, String libName) throws FileNotFoundException, IOException {\r
+        String tmpDirStr = System.getProperty("java.io.tmpdir");\r
+        if (tmpDirStr == null)\r
+            throw new NullPointerException("java.io.tmpdir property is null");\r
+        File tmpDir = new File(tmpDirStr);\r
+        File libFile = new File(tmpDir, libName);\r
+\r
+        if (libFile.exists()) {\r
+            if (libFile.isFile()) {\r
+                try {\r
+                    byte[] origSum = computeSum(libURL);\r
+                    byte[] targetSum = computeSum(libFile);\r
+                    if (Arrays.equals(origSum, targetSum))\r
+                        return libFile;\r
+                } catch (NoSuchAlgorithmException e) {\r
+                    // TODO Auto-generated catch block\r
+                    e.printStackTrace();\r
+                }\r
+            }\r
+        }\r
+\r
+        return copyResource(libURL, libFile);\r
+    }\r
+\r
+    public static byte[] computeSum(InputStream in) throws IOException {\r
+        if (in == null)\r
+            throw new IllegalArgumentException("Input cannot be null!");\r
+\r
+        try {\r
+            MessageDigest md = MessageDigest.getInstance("MD5");\r
+            byte[] data = new byte[64 * 1024];\r
+\r
+            while (true) {\r
+                int read = in.read(data);\r
+                if (read == -1) {\r
+                    return md.digest();\r
+                }\r
+                md.update(data, 0, read);\r
+            }\r
+        } catch (NoSuchAlgorithmException e) {\r
+            // Should not be possible for MD5\r
+            throw new IOException(e);\r
+        }\r
+    }\r
+\r
+    public static byte[] computeSum(File f) throws IOException, NoSuchAlgorithmException {\r
+        InputStream in = null;\r
+        try {\r
+            in = new FileInputStream(f);\r
+            return computeSum(in);\r
+        } finally {\r
+            if (in != null)\r
+                in.close();\r
+        }\r
+    }\r
+\r
+    public static byte[] computeSum(URL url) throws IOException, NoSuchAlgorithmException {\r
+        InputStream in = null;\r
+        try {\r
+            in = url.openStream();\r
+            return computeSum(in);\r
+        } finally {\r
+            if (in != null)\r
+                in.close();\r
+        }\r
+    }\r
+\r
+}
\ No newline at end of file