Package org.menagerie.locks

Source Code of org.menagerie.locks.ReentrantZkLock2Test

/*
* Copyright 2010 Scott Fines
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/
package org.menagerie.locks;

import org.apache.log4j.Logger;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.menagerie.BaseZkSessionManager;
import org.menagerie.TestUtils;
import org.menagerie.ZkSessionManager;
import org.menagerie.ZkUtils;
import org.menagerie.util.TestingThreadFactory;

import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.menagerie.TestUtils.newZooKeeper;

/**
* Unit tests for ReentrantZkLock
* <p>
* Note: These methods will not run without first having a ZooKeeper server started on {@code hostString}.
*
* @author Scott Fines
* @version 1.0
*          Date: 21-Nov-2010
*          Time: 13:49:20
*/
public class ReentrantZkLock2Test {
    private static final Logger logger = Logger.getLogger(ReentrantZkLock2Test.class);
    private static final String hostString = "localhost:2181";
    private static final String baseLockPath = "/test-locks2";
    private static final int timeout = 2000;
    private static final ExecutorService testService = Executors.newFixedThreadPool(2, new TestingThreadFactory());

    private static ZooKeeper zk;
    private static ZkSessionManager zkSessionManager;

    @Before
    public void setup() throws Exception {
        zk = TestUtils.newZooKeeper(hostString, timeout);

        //be sure that the lock-place is created
        ZkUtils.recursiveSafeDelete(zk, baseLockPath, -1);
        zk.create(baseLockPath,new byte[]{}, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);

        zkSessionManager = new BaseZkSessionManager(zk);
    }

    @After
    public void tearDown() throws Exception{
        try{
            List<String> children = zk.getChildren(baseLockPath,false);
            for(String child:children){
                ZkUtils.safeDelete(zk,baseLockPath+"/"+child,-1);
            }
            ZkUtils.safeDelete(zk,baseLockPath,-1);

        }catch(KeeperException ke){
            //suppress because who cares what went wrong after our tests did their thing?
        }finally{
            zk.close();
        }
    }

    @Test(timeout = 1500l)
    public void testOnlyOneLockAllowedTwoThreads()throws Exception{
        final CountDownLatch latch = new CountDownLatch(1);
        Lock firstLock = Locksmith.reentrantLock(zkSessionManager, baseLockPath);

        firstLock.lock();
        try{
            testService.submit(new Runnable() {
                @Override
                public void run() {
                    Lock secondLock = new ReentrantZkLock2(baseLockPath, zkSessionManager);
                    secondLock.lock();
                    try{
                        latch.countDown();
                    }finally{
                        secondLock.unlock();
                    }
                }
            });

            boolean nowAcquired = latch.await(500, TimeUnit.MILLISECONDS);
            assertTrue("The Second lock was acquired before the first lock was released!",!nowAcquired);
        }finally{
            firstLock.unlock();
        }
    }


    @Test(timeout = 1500l)
    public void testReentrancy()throws Exception{
        final CountDownLatch latch = new CountDownLatch(1);
        Lock firstLock = new ReentrantZkLock2(baseLockPath, zkSessionManager);
        firstLock.lock();
        try{
            testService.submit(new Runnable() {
                @Override
                public void run() {
                    Lock secondLock = new ReentrantZkLock2(baseLockPath, zkSessionManager);
                    secondLock.lock();
                    try{
                        latch.countDown();
                    }finally{
                        secondLock.unlock();
                    }
                }
            });

            boolean nowAcquired = latch.await(500, TimeUnit.MILLISECONDS);
            assertTrue("The Second lock was acquired before the first lock was released!",!nowAcquired);

            //this should be fine
            firstLock.lock();
            firstLock.unlock();
            //should still be locked
            nowAcquired = latch.await(500, TimeUnit.MILLISECONDS);
            assertTrue("The Second lock was acquired before the first lock was released twice!",!nowAcquired);
        }finally{
            firstLock.unlock();
        }
    }

    @Test(timeout = 1500l)
    public void testMultipleThreadsCannotAccessSameLock()throws Exception{
        final CountDownLatch latch = new CountDownLatch(1);
        final Lock firstLock = new ReentrantZkLock2(baseLockPath, zkSessionManager);
        firstLock.lock();
        testService.submit(new Runnable() {
            @Override
            public void run() {
                firstLock.lock();
                try{
                    latch.countDown();
                }finally{
                    firstLock.unlock();
                }
            }
        });

        boolean acquired = latch.await(500, TimeUnit.MILLISECONDS);
        assertTrue("The Lock was acquired twice by two separate threads!",!acquired);

        firstLock.unlock();

        acquired = latch.await(500, TimeUnit.MILLISECONDS);
        assertTrue("The Lock was never acquired by another thread!",acquired);

    }

    @Test(timeout = 1000l)
    public void testMultipleClientsCannotAccessSameLock()throws Exception{
        final CountDownLatch latch = new CountDownLatch(1);
        final Lock firstLock = new ReentrantZkLock2(baseLockPath, zkSessionManager);


        firstLock.lock();
        Future<Void> errorFuture = testService.submit(new Callable<Void>() {
            @Override
            public Void call() throws Exception {
                ZooKeeper newZk = TestUtils.newZooKeeper(hostString, timeout);
                try {
                    final Lock sameLock = new ReentrantZkLock2(baseLockPath, new BaseZkSessionManager(newZk));
                    sameLock.lock();
                    try {
                        latch.countDown();
                    } finally {
                        sameLock.unlock();
                    }
                } finally {
                    newZk.close();
                }
                return null;
            }
        });

        boolean acquired = latch.await(500, TimeUnit.MILLISECONDS);
        assertTrue("The Lock was acquired twice by two separate threads!",!acquired);

        firstLock.unlock();

        acquired = latch.await(500, TimeUnit.MILLISECONDS);
        assertTrue("The Lock was never acquired by another thread!",acquired);
        errorFuture.get(); //check for errors
    }


    @Test(timeout = 1000l)
    public void testLockTimesOutWaiting() throws Exception{
        final CountDownLatch latch = new CountDownLatch(1);
        Lock firstLock = new ReentrantZkLock2(baseLockPath, zkSessionManager);
        firstLock.lock();
        try{
            testService.submit(new Runnable() {
                @Override
                public void run() {
                    Lock secondLock = new ReentrantZkLock2(baseLockPath, zkSessionManager);
                    try {
                        boolean acquired = secondLock.tryLock(300, TimeUnit.MILLISECONDS);
                        if(acquired){
                            try{
                                latch.countDown();
                            }finally{
                                secondLock.unlock();
                            }
                        }else{
                            System.out.println("Lock was not acquired in 300 milliseconds");
                        }
                    } catch (InterruptedException e) {
                        fail(e.getMessage());
                    }
                }
            });

            boolean acquired =latch.await(500, TimeUnit.MILLISECONDS);
            assertTrue("Lock was acquired too early!",!acquired);
        }finally{
            firstLock.unlock();
        }
    }

    @Test(timeout = 1000l)
    public void testLockInterruptiblyWorksDifferentInstances() throws Exception{
        final CountDownLatch latch = new CountDownLatch(1);
        Lock firstLock = new ReentrantZkLock2(baseLockPath, zkSessionManager);
        firstLock.lockInterruptibly();
        Future<Void>errorFuture;
        try{
            errorFuture = testService.submit(new Callable<Void>() {
                @Override
                public Void call() throws Exception {
                    Lock secondLock = new ReentrantZkLock2(baseLockPath, zkSessionManager);
                    logger.debug("interruptible acquiring lock");
                    secondLock.lockInterruptibly();
                    logger.debug("acquired");
                    try {
                        latch.countDown();
                    } finally {
                        secondLock.unlock();
                    }
                    return null;
                }
            });
            logger.debug("Waiting for latch...");
            boolean nowAcquired = latch.await(500, TimeUnit.MILLISECONDS);
            logger.debug("Latch completed");
            assertTrue("The Second lock was acquired before the first lock was released!", !nowAcquired);

        }finally{
            logger.debug("Unlocking...");
            firstLock.unlock();
            logger.debug("Unlocked");
        }
        //make sure that no errors happen
        errorFuture.get();
    }

    @Test(timeout = 1000l)
    public void testLockInterruptiblyWorksSameInstance() throws Exception{
        final CountDownLatch latch = new CountDownLatch(1);
        final Lock firstLock = new ReentrantZkLock2(baseLockPath, zkSessionManager);
        firstLock.lockInterruptibly();
        Future<Void>errorFuture;
        try{
            errorFuture = testService.submit(new Callable<Void>() {
                @Override
                public Void call() throws Exception {
//                    Lock secondLock = new ReentrantZkLock(baseLockPath, commandExecutor);
                    firstLock.lockInterruptibly();
                    try {
                        latch.countDown();
                    } finally {
                        firstLock.unlock();
                    }
                    return null;
                }
            });

            boolean nowAcquired = latch.await(500, TimeUnit.MILLISECONDS);
            assertTrue("The Second lock was acquired before the first lock was released!",!nowAcquired);

        }finally{
            firstLock.unlock();
        }
        //make sure that no errors happen
        errorFuture.get();
    }

    @Test(timeout = 2000l)
    public void testLockInterruptiblyIsInterruptibleDifferentLockInstances() throws Exception{
        /*
        The idea here is to test to ensure that we can interrupt the
        acquisition of a lockInterruptibly call from another thread, using a different
        instance of the same distributed lock
        */
        Lock mainLock = new ReentrantZkLock2(baseLockPath,zkSessionManager);
        mainLock.lock();
        final CyclicBarrier latch = new CyclicBarrier(2);
        try{
            final AtomicBoolean bool = new AtomicBoolean();
            Thread t = new Thread() {
                @Override
                public void run() {
                    Lock secondaryLock = new ReentrantZkLock2(baseLockPath, zkSessionManager);
                    boolean thrown = false;
                    try {
                        System.out.printf("%s: Attempting to acquire the lock interruptibly%n",Thread.currentThread().getName());
                        latch.await();
                        secondaryLock.lockInterruptibly();
                        fail("secondary Lock was acquired improperly!");
                    } catch (InterruptedException ie) {
                        System.out.printf("%s: Secondary lock threw an InterruptedException$n",Thread.currentThread().getName());
                        thrown = true;
                    } catch (BrokenBarrierException e) {
                        fail(e.getMessage());
                    }
                    bool.set(thrown);
                }
            };
            t.setName("secondary-thread");
            t.start();
            //make sure that the thread is set
            latch.await();
            Thread.sleep(300);
            //now interrupt the thread
            System.out.printf("%s: Interrupting secondary thread: %s%n",Thread.currentThread().getName(),t.getName());
            t.interrupt();
            //now make sure that we get back true
            t.join();
            assertTrue("Thread was not interrupted successfully!",bool.get());
        }finally{
            mainLock.unlock();
        }
    }

    @Test(timeout = 2000l)
    public void testLockInterruptiblyIsInterruptibleSameLockInstance() throws Exception{
        /*
        The idea here is to test to ensure that we can interrupt the
        acquisition of a lockInterruptibly call from another thread, using a different
        instance of the same distributed lock
        */
        Lock mainLock = new ReentrantZkLock2(baseLockPath,zkSessionManager);
        mainLock.lock();
        final CyclicBarrier latch = new CyclicBarrier(2);
        try{
            final AtomicBoolean bool = new AtomicBoolean();
            Thread t = new Thread() {
                @Override
                public void run() {
                    Lock secondaryLock = new ReentrantZkLock2(baseLockPath, zkSessionManager);
                    boolean thrown = false;
                    try {
                        System.out.printf("%s: Attempting to acquire the lock interruptibly%n",Thread.currentThread().getName());
                        latch.await();
                        secondaryLock.lockInterruptibly();
                        fail("secondary Lock was acquired improperly!");
                    } catch (InterruptedException ie) {
                        System.out.printf("%s: Secondary lock threw an InterruptedException$n",Thread.currentThread().getName());
                        thrown = true;
                    } catch (BrokenBarrierException e) {
                        fail(e.getMessage());
                    }
                    bool.set(thrown);
                }
            };
            t.setName("secondary-thread");
            t.start();
            //make sure that the thread is set
            latch.await();
            Thread.sleep(300);
            //now interrupt the thread
            System.out.printf("%s: Interrupting secondary thread: %s%n",Thread.currentThread().getName(),t.getName());
            t.interrupt();
            //now make sure that we get back true
            t.join();
            assertTrue("Thread was not interrupted successfully!",bool.get());
        }finally{
            mainLock.unlock();
        }
    }

    @Test(timeout = 2000l)
    public void testLockInterruptiblyInterruptibleIfThreadAlreadyInterruptedOnEntry() throws Exception{
        /*
        The idea here is to test that, if the thread we have is interrupted BEFORE entry into the method,
        that it throws an InterruptedException.
        */
        final AtomicBoolean bool = new AtomicBoolean();

        Thread t = new Thread(){

            @Override
            public void run() {
                ReentrantZkLock2 lock = new ReentrantZkLock2(baseLockPath, zkSessionManager);
                //interrupt the current thread
                Thread.currentThread().interrupt();

                logger.debug("Attempting to acquire interruptibly. Expected InterruptedException");


                logger.trace("Is current thread interrupted()?"+Thread.currentThread().isInterrupted());
                //now try to lock interruptibly

                try {
                    lock.lockInterruptibly();
                } catch (InterruptedException e) {
                    bool.set(true);
                    return;
                }
                bool.set(false);
            }
        };

        t.start();
        t.join();

        //now check that we were interrupted
        assertTrue("Lock was not interrupted before entry!",bool.get());
    }

    @Test(timeout = 1000l)
    public void testLockInterruptiblyReentrant() throws Exception{
        Lock lock = new ReentrantZkLock2(baseLockPath,zkSessionManager);
        lock.lockInterruptibly();
        try{
            //try to enter the lock again
            lock.lockInterruptibly();
            //success! we're gravy
            lock.unlock();
        }finally{
            lock.unlock();
        }
    }


    @Test(timeout = 1000l)
    public void testTryLockWorksWithNoContention() throws Exception{
        Lock keptLock = new ReentrantZkLock2(baseLockPath,zkSessionManager);
        boolean acquired = keptLock.tryLock();
        assertTrue("Lock did not acquire!",acquired);
        keptLock.unlock();
    }

    @Test(timeout = 1000l)
    public void testTryLockReturnsFalseWhenSomeoneElseHasItDifferentInstances() throws Exception{
        Lock keptLock = new ReentrantZkLock2(baseLockPath,zkSessionManager);
        keptLock.lock();
        try{
            final Future<Boolean> falseFuture = testService.submit(new Callable<Boolean>() {
                @Override
                public Boolean call() throws Exception {
                    Lock failLock = new ReentrantZkLock2(baseLockPath, zkSessionManager);
                    return failLock.tryLock();
                }
            });
            assertTrue("Try lock incorrectly acquired!",!falseFuture.get());
        }finally{
            keptLock.unlock();
        }
    }

    @Test(timeout = 1000l)
    public void testTryLockReturnsFalseWhenSomeoneElseHasItSameInstance() throws Exception{
        final Lock keptLock = new ReentrantZkLock2(baseLockPath,zkSessionManager);
        keptLock.lock();
        try{
            final Future<Boolean> falseFuture = testService.submit(new Callable<Boolean>() {
                @Override
                public Boolean call() throws Exception {
                    return keptLock.tryLock();
                }
            });
            assertTrue("second thread incorrectly acquired lock!",!falseFuture.get());
        }finally{
            keptLock.unlock();
        }
    }

    @Test(timeout = 1000l)
    public void testTryLockInterruptibleBeforeEntry() throws Exception{
         /*
        The idea here is to test that, if the thread we have is interrupted BEFORE entry into the method,
        that it throws an InterruptedException.
        */
        final AtomicBoolean bool = new AtomicBoolean();

        Thread t = new Thread(){

            @Override
            public void run() {
                ReentrantZkLock2 lock = new ReentrantZkLock2(baseLockPath, zkSessionManager);
                //interrupt the current thread
                Thread.currentThread().interrupt();

                logger.debug("Attempting to acquire interruptibly. Expected InterruptedException");


                logger.trace("Is current thread interrupted()?"+Thread.currentThread().isInterrupted());
                //now try to lock interruptibly

                try {
                    lock.tryLock(Long.MAX_VALUE,TimeUnit.DAYS);
                } catch (InterruptedException e) {
                    bool.set(true);
                    return;
                }
                bool.set(false);
            }
        };

        t.start();
        t.join();

        //now check that we were interrupted
        assertTrue("Lock was not interrupted before entry!",bool.get());
    }

    @Test(timeout = 1000l)
    public void testTryLockReentrant() throws Exception{
        Lock lock = new ReentrantZkLock2(baseLockPath,zkSessionManager);
        lock.tryLock();
        try{
            lock.tryLock();
            lock.unlock();
        }finally{
            lock.unlock();
        }

    }


    @Test(timeout = 1000l)
    public void testTimedTryLockWorks() throws Exception{
        Lock lock = new ReentrantZkLock2(baseLockPath,zkSessionManager);
        logger.debug("Acquiring the lock for the first time...");
        lock.tryLock(Long.MAX_VALUE,TimeUnit.DAYS);
        //we are good, lock was acquired!
        lock.unlock();
    }

    @Test(timeout = 1000l)
    public void testTimedTryLockReentrant() throws Exception{
        Lock lock = new ReentrantZkLock2(baseLockPath,zkSessionManager);
        logger.debug("Acquiring the lock for the first time...");
        lock.tryLock(Long.MAX_VALUE,TimeUnit.DAYS);
        try{
            logger.debug("Attempting to re-acquire the lock on the same thread");
            lock.tryLock(Long.MAX_VALUE,TimeUnit.DAYS);
            lock.unlock();
        }finally{
            lock.unlock();
        }

    }

    @Test(timeout = 1000l)
    public void testUnlockWorks() throws Exception{
        Lock lock = new ReentrantZkLock2(baseLockPath,zkSessionManager);
        logger.debug("Acquiring the lock for the first time...");
        lock.lock();
        //we are good, lock was acquired!
        lock.unlock();

        //see if you can lock it again
        lock.lock();

        lock.unlock();
    }


    @Test(timeout = 1500l)
    @Ignore("Ignored until Conditions are fully implemented in ReentrantZkLock2")
    public void testConditionWaitsForSignalOtherThread() throws Exception{
        final Lock firstLock = new ReentrantZkLock2(baseLockPath, zkSessionManager);
        final Condition firstCondition = firstLock.newCondition();

        firstLock.lock();
        //fire off a thread that will signal the main process thread
        testService.submit(new Runnable() {
            @Override
            public void run() {
                firstLock.lock();
                System.out.println("Lock acquired on second thread");
                try{
                    firstCondition.signal();
                    System.out.println("Lock signalled on second thread");
                }finally{
                    System.out.println("Lock released on second thread");
                    firstLock.unlock();
                }
            }
        });

        //wait for signal notification
        System.out.println("First thread waiting for notification");
        firstCondition.await();
        System.out.println("First thread has been notified");
    }

    @Test(timeout = 1500l)
    @Ignore("Ignored until Conditions are fully implemented in ReentrantZkLock2")
    public void testConditionWaitsForSignalOtherClient() throws Exception{
        final Lock firstLock = new ReentrantZkLock2(baseLockPath, zkSessionManager);
        final Condition firstCondition = firstLock.newCondition();

        firstLock.lock();
        //fire off a thread that will signal the main process thread
        testService.submit(new Callable<Void>() {
            @Override
            public Void call() throws Exception{
                final Lock otherClientLock;
                ZooKeeper newZk = newZooKeeper(hostString,timeout);
                try {
                    otherClientLock = new ReentrantZkLock2(baseLockPath, new BaseZkSessionManager(newZk));
                    final Condition otherClientCondition = otherClientLock.newCondition();
                    otherClientLock.lock();
                    System.out.println("Lock acquired on second thread");
                    try{
                        otherClientCondition.signal();
                        System.out.println("Lock signalled on second thread");
                    }finally{
                        System.out.println("Lock released on second thread");
                        otherClientLock.unlock();
                    }
                }finally{
                    newZk.close();
                }
                return null;
            }
        });

        //wait for signal notification
        System.out.println("First thread waiting for notification");
        firstCondition.await();
        System.out.println("First thread has been notified");
        firstLock.unlock();
    }

    @Test(timeout = 1000l)
    @Ignore("Ignored until Conditions are fully implemented in ReentrantZkLock2")
    public void testConditionTimesOut() throws Exception{
        Lock firstLock = new ReentrantZkLock2(baseLockPath,zkSessionManager);
        Condition firstCondition = firstLock.newCondition();

        firstLock.lock();
        boolean timedOut = firstCondition.await(250l, TimeUnit.MILLISECONDS);
        assertTrue("Condition did not time out!",!timedOut);
        firstLock.unlock();
    }


    @Test(timeout = 10000l)
    public void testLockWorksUnderContentionDifferentClients() throws Exception{
        int numThreads = 5;
        final int numIterations = 100;
        ExecutorService service = Executors.newFixedThreadPool(numThreads);
        final CyclicBarrier startBarrier = new CyclicBarrier(numThreads+1);
        final CyclicBarrier endBarrier = new CyclicBarrier(numThreads+1);

        final UnsafeOperator operator = new UnsafeOperator();
        for(int i=0;i<numThreads;i++){
            service.submit(new Callable<Void>() {
                @Override
                public Void call() throws Exception {
                    startBarrier.await(); //make sure all threads are in the same place before starting

                    //create the lock that we're going to use
                    ZooKeeper zk = newZooKeeper(hostString,timeout);
                    try{
                        Lock testLock = new ReentrantZkLock2(baseLockPath,new BaseZkSessionManager(zk));
                        for(int j=0;j<numIterations;j++){
                            testLock.lock();
                            try{
                                operator.increment();
                            }finally{
                                testLock.unlock();
                            }
                        }
                    }finally{
                        zk.close();
                    }

                    //enter the end barrier to ensure that things are finished
                    endBarrier.await();
                    return null;
                }
            });
        }

        //start the test
        startBarrier.await();

        //wait for the end of the test
        endBarrier.await();

        //check that the number of operations that actually were recorded are correct
        int correctOps = numIterations*numThreads;
        assertEquals("Number of Operations recorded was incorrect!",correctOps,operator.getValue());
    }

    @Test(timeout = 20000l)
    public void testLockWorksUnderContentionSameClient() throws Exception{
        int numThreads = 5;
        final int numIterations = 100;
        ExecutorService service = Executors.newFixedThreadPool(numThreads);
        final CyclicBarrier startBarrier = new CyclicBarrier(numThreads+1);
        final CyclicBarrier endBarrier = new CyclicBarrier(numThreads+1);

        final UnsafeOperator operator = new UnsafeOperator();
        final Lock testLock = new ReentrantZkLock2(baseLockPath,zkSessionManager);
        for(int i=0;i<numThreads;i++){
            service.submit(new Callable<Void>() {
                @Override
                public Void call() throws Exception {
                    startBarrier.await(); //make sure all threads are in the same place before starting

                    for(int j=0;j<numIterations;j++){
                        testLock.lock();
                        try{
                            operator.increment();
                        }finally{
                            testLock.unlock();
                        }
                    }

                    //enter the end barrier to ensure that things are finished
                    endBarrier.await();
                    return null;
                }
            });
        }

        //start the test
        startBarrier.await();

        //wait for the end of the test
        endBarrier.await();

        //check that the number of operations that actually were recorded are correct
        int correctOps = numIterations*numThreads;
        assertEquals("Number of Operations recorded was incorrect!",correctOps,operator.getValue());
    }




}
TOP

Related Classes of org.menagerie.locks.ReentrantZkLock2Test

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.