1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.db.procore.server.environment.windows;
14 import java.io.Closeable;
16 import java.io.FileInputStream;
17 import java.io.FileNotFoundException;
18 import java.io.FileOutputStream;
19 import java.io.IOException;
20 import java.io.InputStream;
22 import java.net.URLDecoder;
23 import java.security.MessageDigest;
24 import java.security.NoSuchAlgorithmException;
25 import java.util.Arrays;
27 import org.simantics.db.procore.server.environment.ExecutionEnvironment;
28 import org.simantics.db.procore.server.environment.ExecutionEnvironmentException;
31 * Provides Java access to Windows Msi API functions:
33 * <li>{@link #MsiQueryProductState(String)} (see <a
34 * href="http://msdn.microsoft.com/en-us/library/aa370363(VS.85).aspx">MSDN</a>)</li>
37 * @author Tuukka Lehtonen
41 public static void checkOneOfProductsInstalled(Product... products) throws ExecutionEnvironmentException {
42 StringBuilder sb = new StringBuilder();
43 sb.append("None of the following products are installed properly:\n");
44 for (Product product : products) {
45 ProductState state = Msi.MsiQueryProductState(product.getCode());
48 // One of the listed products is installed OK.
51 sb.append("\t" + product);
52 sb.append(" - MsiQueryProductState returned ");
57 throw new ExecutionEnvironmentException("Cannot run ProCore database server in this environment due to the following problems:\n" + sb.toString(), Arrays.asList(products));
60 public static void checkProductsInstalled(Product... products) throws ExecutionEnvironmentException {
61 StringBuilder sb = new StringBuilder();
62 for (Product product : products) {
63 ProductState state = Msi.MsiQueryProductState(product.getCode());
69 sb.append("\tProduct " + product + " is not installed properly, MsiQueryProductState returned " + state);
73 if (sb.length() > 0) {
74 // Something is not installed right, throw exception
75 throw new ExecutionEnvironmentException("Cannot run ProCore database server in this environment due to the following problems:\n" + sb.toString(), Arrays.asList(products));
79 // -------------------------------------------------------------------------
81 public static ProductState MsiQueryProductState(String productCode) {
82 int result = MsiQueryProductState0(productCode);
83 return ProductState.of(result);
86 private static native int MsiQueryProductState0(String productCode);
88 // -------------------------------------------------------------------------
90 private static final String DLL_NAME = "msijni.dll";
91 private static final String DLL_NAME_64 = "msijni64.dll";
97 private static void initialize() {
98 ExecutionEnvironment env = ExecutionEnvironment.calculate();
99 String libName = null;
105 libName = DLL_NAME_64;
111 URL libURL = Msi.class.getResource("/" + libName);
112 if (libURL != null) {
114 if ("file".equals(libURL.getProtocol())) {
115 File path = new File(URLDecoder.decode(libURL.getPath(), "UTF-8"));
118 File libFile = extractLib(libURL, libName);
121 } catch (IOException e) {
127 private static void initialize(File path) {
128 //System.out.println("load msijni: " + path);
129 System.load(path.toString());
133 * Extracts the specified source file in the specified bundle into the
134 * specified local directory.
136 * @param url the source URL to stream the resource from
137 * @param targetFile the target file to write the resource to
138 * @param deleteOnExit <code>true</code> to use {@link File#deleteOnExit()}
139 * on the resulting file. Note that this does not guarantee that the
140 * file is deleted when the JVM exits
141 * @return the resulting file
142 * @throws FileNotFoundException
144 private static File copyResource(URL url, File targetFile) throws IOException, FileNotFoundException {
145 FileOutputStream os = null;
146 InputStream is = null;
148 if (targetFile.exists())
151 is = url.openStream();
153 byte [] buffer = new byte [16384];
154 os = new FileOutputStream (targetFile);
155 while ((read = is.read (buffer)) != -1) {
156 os.write(buffer, 0, read);
169 private static void uncheckedClose(Closeable closeable) {
171 if (closeable != null)
173 } catch (IOException e) {
178 private static File extractLib(URL libURL, String libName) throws FileNotFoundException, IOException {
179 String tmpDirStr = System.getProperty("java.io.tmpdir");
180 if (tmpDirStr == null)
181 throw new NullPointerException("java.io.tmpdir property is null");
182 File tmpDir = new File(tmpDirStr);
183 File libFile = new File(tmpDir, libName);
185 if (libFile.exists()) {
186 if (libFile.isFile()) {
188 byte[] origSum = computeSum(libURL);
189 byte[] targetSum = computeSum(libFile);
190 if (Arrays.equals(origSum, targetSum))
192 } catch (NoSuchAlgorithmException e) {
193 // TODO Auto-generated catch block
199 return copyResource(libURL, libFile);
202 public static byte[] computeSum(InputStream in) throws IOException {
204 throw new IllegalArgumentException("Input cannot be null!");
207 MessageDigest md = MessageDigest.getInstance("MD5");
208 byte[] data = new byte[64 * 1024];
211 int read = in.read(data);
215 md.update(data, 0, read);
217 } catch (NoSuchAlgorithmException e) {
218 // Should not be possible for MD5
219 throw new IOException(e);
223 public static byte[] computeSum(File f) throws IOException, NoSuchAlgorithmException {
224 InputStream in = null;
226 in = new FileInputStream(f);
227 return computeSum(in);
234 public static byte[] computeSum(URL url) throws IOException, NoSuchAlgorithmException {
235 InputStream in = null;
237 in = url.openStream();
238 return computeSum(in);