UniqueIdSeed.java

package org.microspace.util;

import java.io.File;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;


/**
 * UniqueId is using this seed internally.
 * 
 * @author Gaspar Sinai - {@literal gaspar.sinai@microspace.org}
 * @version 2016-06-26
 */
class UniqueIdSeed {
	
	private static final byte[] DEFAULT_MAC = { 0, 0, 0, 0, 0 , 0 };
	
	public enum ProcessIdSource {
		NONE, JMX, PROCHANDLE, PROCFS
	}

	private byte[] macAddress;
	private long time;
	private int processId;
	
	ProcessIdSource processIdSource;
	
	public UniqueIdSeed() {
		processIdSource = ProcessIdSource.NONE;
		byte [] mac = null;
		try {
			Enumeration<NetworkInterface> nifs = NetworkInterface.getNetworkInterfaces();
			while (nifs.hasMoreElements()) {
				NetworkInterface nif = nifs.nextElement();
				if (nif.isLoopback()) continue;
				if (nif.isVirtual()) continue;
				if (!nif.isUp()) continue;
				mac = nif.getHardwareAddress();
				if (mac != null) break; 
			}
			if (mac == null) mac	 = DEFAULT_MAC;
		} catch (SocketException e) {
			mac = DEFAULT_MAC;	
		}
		macAddress = mac;

        // From http://stackoverflow.com/questions/35842/how-can-a-java-program-get-its-own-process-id
        // Works everywhere till RunTimeMXBean exists
		if (processIdSource == ProcessIdSource.NONE) { 
			try {
			// Using reflexion for this java9 feature.
			//processId = (int)ProcessHandle.current().pid();
			Class<?> processHandleClass = 
						Class.forName("java.lang.ProcessHandle");
			Method currentMethod = processHandleClass.getMethod("current");
			Object processHandleInstance = currentMethod.invoke(null);
			Method pidMethod =processHandleClass.getMethod("pid");
			//pidMethod.setAccessible(true);
			processId = (int) ((long) pidMethod.invoke(processHandleInstance));
			processIdSource = ProcessIdSource.PROCHANDLE;
			} catch (Exception ex) {
			// ex.printStackTrace();
			}
		}
		if (processIdSource == ProcessIdSource.NONE) { 
		    try {
                RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
                Field jvm = runtime.getClass().getDeclaredField("jvm");
                jvm.setAccessible(true);
			    Object mgmt = jvm.get(runtime);
                java.lang.reflect.Method pid_method = mgmt.getClass().getDeclaredMethod("getProcessId");
                pid_method.setAccessible(true);
                processId = (Integer) pid_method.invoke(mgmt);
                processIdSource = ProcessIdSource.JMX;
		    } catch (Exception e0) {
            }
        }
        if (processIdSource == ProcessIdSource.NONE) {
            // Linux only.
		    try {
                processId = Integer.parseInt(new File("/proc/self").getCanonicalFile().getName());
                processIdSource = ProcessIdSource.PROCFS;  
		    } catch (Exception e) {
            	
            }
        }
		time = System.currentTimeMillis();
	}

	public byte[] getMacAddress() {
		return macAddress;
	}

	public long getTime() {
		return time;
	}

	public int getProcessId() {
		return processId;
	}
	public ProcessIdSource getProcessIdSource() {
		return processIdSource;
	}
	
	
	
}