/******************************************************************************* * Copyright (c) 2013 hangum. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Lesser Public License v2.1 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * * Contributors: * hangum - initial API and implementation ******************************************************************************/ package com.hangum.tadpole.commons.util; import java.io.File; import java.io.FileOutputStream; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; import org.apache.log4j.Logger; import org.eclipse.core.runtime.Platform; import com.hangum.tadpole.commons.libs.core.define.SystemDefine; /** * application lock * * referecne code : http://fresh2l.com/en/blog/2011/01/08/howto-run-only-single-java-application-instance * * @author hangum * */ public class ApplicationLock { private static final Logger logger = Logger.getLogger(ApplicationLock.class); /** hidden constructor */ private ApplicationLock() { } /** Lock file */ File lock_file = null; FileLock lock = null; FileChannel lock_channel = null; FileOutputStream lock_stream = null; /** * Creates class lock instance * * @param key * Unique application key */ private ApplicationLock(String key) throws Exception { try { String tmp_dir = SystemDefine.getConfigureRoot() + "configuration/tadpole/temp/"; File tmpDir = new File(tmp_dir); if(!tmpDir.isDirectory()) { tmpDir.mkdirs(); } if(logger.isDebugEnabled()) { logger.debug("Application temp dir is " + tmp_dir); } // Acquire MD5 try { java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5"); md.reset(); String hash_text = new java.math.BigInteger(1, md.digest(key.getBytes())).toString(16); while (hash_text.length() < 32) { hash_text = "0" + hash_text; } lock_file = new File(tmp_dir + hash_text + ".app_lock"); } catch (Exception ex) { logger.error("lock_file", ex); } // MD5 acquire fail if (lock_file == null) { lock_file = new File(tmp_dir + key + ".app_lock"); } lock_stream = new FileOutputStream(lock_file); String f_content = "Tadpole DB Hub Application \r\nLocked by key: " + key + "\r\n"; lock_stream.write(f_content.getBytes()); lock_channel = lock_stream.getChannel(); lock = lock_channel.tryLock(); if (lock == null) { throw new Exception("Can't create Lock"); } } catch(Exception e) { logger.error("last error", e); throw e; } } /** * Remove Lock. Now another application instance can gain lock. * * @throws Throwable */ private void release() throws Throwable { if (lock != null) { lock.release(); } if (lock_channel != null) { lock_channel.close(); } if (lock_stream != null) { lock_stream.close(); } if (lock_file != null) { lock_file.delete(); } } @Override protected void finalize() throws Throwable { this.release(); super.finalize(); } private static ApplicationLock instance; /** * Set Lock based on input key Method can be run only one time per * application. Second calls will be ignored. * * @param key * Lock key */ public static boolean setLock(String key) { if (instance != null) { return true; } try { instance = new ApplicationLock(key); } catch (Exception ex) { instance = null; logger.error("set lock", ex); return false; } Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { ApplicationLock.releaseLock(); } }); return true; } /** * Try to release Lock. After releasing you can not user AppLock again in * application. */ public static void releaseLock() { if (instance == null) { return; } try { instance.release(); } catch (Throwable ex) { logger.error("release lock", ex); } } }