Example usage for org.apache.zookeeper WatchedEvent getState

List of usage examples for org.apache.zookeeper WatchedEvent getState

Introduction

In this page you can find the example usage for org.apache.zookeeper WatchedEvent getState.

Prototype

public KeeperState getState() 

Source Link

Usage

From source file:io.reign.AbstractZkEventHandler.java

License:Apache License

@Override
public void process(WatchedEvent event) {
    /** log event **/
    // log if TRACE
    if (logger.isTraceEnabled()) {
        logger.trace("***** Received ZooKeeper Event:  {}",
                ReflectionToStringBuilder.toString(event, ToStringStyle.DEFAULT_STYLE));

    }/*from  w  w w.java  2s.  c  o  m*/

    /** check if we are filtering this event **/
    if (filterWatchedEvent(event)) {
        return;
    }

    /** process events **/
    switch (event.getType()) {
    case NodeChildrenChanged:
        nodeChildrenChanged(event);
        break;
    case NodeCreated:
        nodeCreated(event);
        break;
    case NodeDataChanged:
        nodeDataChanged(event);
        break;
    case NodeDeleted:
        nodeDeleted(event);
        break;
    case None:
        Event.KeeperState eventState = event.getState();
        if (eventState == Event.KeeperState.SyncConnected) {
            connected(event);
        } else if (eventState == Event.KeeperState.Disconnected) {
            disconnected(event);
        } else if (eventState == Event.KeeperState.Expired) {
            sessionExpired(event);
        } else {
            logger.warn("Unhandled event state:  eventType={}; eventState={}", event.getType(),
                    event.getState());
        }
        break;
    default:
        logger.warn("Unhandled event type:  eventType={}; eventState={}", event.getType(), event.getState());
    }
}

From source file:io.reign.coord.ZkLockWatcher.java

License:Apache License

@Override
public void process(WatchedEvent event) {
    // log if DEBUG
    if (logger.isDebugEnabled()) {
        logger.debug("***** Received ZooKeeper Event:  {}",
                ReflectionToStringBuilder.toString(event, ToStringStyle.DEFAULT_STYLE));

    }/*from ww w.  j a  va  2 s  .c  o m*/

    // process events
    switch (event.getType()) {
    case NodeCreated:
    case NodeChildrenChanged:
    case NodeDataChanged:
    case NodeDeleted:
        synchronized (this) {
            this.notifyAll();

            if (logger.isDebugEnabled()) {
                logger.debug("Notifying threads waiting on LockWatcher:  lockWatcher.hashcode()="
                        + this.hashCode() + "; instancesOutstanding=" + instancesOutstanding.get()
                        + "; lockName=" + lockPath + "; lockReservation=" + lockReservationPath);
            }
        }
        break;

    case None:
        Event.KeeperState eventState = event.getState();
        if (eventState == Event.KeeperState.SyncConnected) {
            // connection event: check children
            synchronized (this) {
                this.notifyAll();
            }

        } else if (eventState == Event.KeeperState.Disconnected || eventState == Event.KeeperState.Expired) {
            // disconnected: notifyAll so we can check children again on
            // reconnection
            synchronized (this) {
                this.notifyAll();
            }

        } else {
            logger.warn("Unhandled event state:  "
                    + ReflectionToStringBuilder.toString(event, ToStringStyle.DEFAULT_STYLE));
        }
        break;

    default:
        logger.warn("Unhandled event type:  "
                + ReflectionToStringBuilder.toString(event, ToStringStyle.DEFAULT_STYLE));
    }

    // }// if

}

From source file:io.reign.zk.ResilientZkClient.java

License:Apache License

@Override
public void process(final WatchedEvent event) {
    /***** log event *****/
    // log if TRACE
    if (logger.isTraceEnabled()) {
        logger.trace("***** Received ZooKeeper Event:  {}",
                ReflectionToStringBuilder.toString(event, ToStringStyle.DEFAULT_STYLE));

    }//from   w w  w.j av a2s  .c  o  m

    /***** pass notifications on to registered Watchers *****/
    // if (event.getType() != EventType.None) {
    if (shutdown) {
        logger.warn("Already shutdown:  not passing event to registered watchers:  type={}; path={}",
                event.getType(), event.getPath());
        return;
    } else {
        for (Watcher watcher : watcherSet) {
            watcher.process(event);
        }
    }
    // }

    /***** process events *****/
    switch (event.getType()) {
    case NodeChildrenChanged:
        this.childWatchesMap.remove(event.getPath());
        break;
    case NodeCreated:
    case NodeDataChanged:
    case NodeDeleted:
        this.dataWatchesMap.remove(event.getPath());
        break;
    case None:
        Event.KeeperState eventState = event.getState();
        if (eventState == Event.KeeperState.SyncConnected) {

            // this.connected = true;

            if (currentSessionId == null) {
                if (logger.isInfoEnabled()) {
                    logger.info(
                            "Restoring watches as necessary:  sessionId={}; connectString={}; sessionTimeout={}",
                            new Object[] { this.zooKeeper.getSessionId(), getConnectString(),
                                    getSessionTimeout() });
                }
                restoreWatches();
            }

            this.currentSessionId = this.zooKeeper.getSessionId();
            this.sessionPassword = this.zooKeeper.getSessionPasswd();

            logger.info("SyncConnected:  notifying all waiters:  currentSessionId={}; connectString={}",
                    currentSessionId, getConnectString());
            synchronized (this) {
                // notify waiting threads that connection has been
                // established
                this.notifyAll();
            }
            logger.info("SyncConnected:  notified all waiters:  currentSessionId={}; connectString={}",
                    currentSessionId, getConnectString());

        } else if (eventState == Event.KeeperState.Disconnected) {
            // this.connected = false;

        } else if (eventState == Event.KeeperState.Expired) {
            // expired session; close ZK connection and reconnect
            if (!this.shutdown) {
                // if session has been expired, clear out the existing ID
                logger.info(
                        "Session has been expired by ZooKeeper cluster:  reconnecting to establish new session:  oldSessionId={}; connectString={}",
                        currentSessionId, getConnectString());

                // null out current session ID
                this.currentSessionId = null;

                // do connection in another thread so as to not block the ZK event thread
                spawnReconnectThread();
            }

        } else {
            logger.warn("Unhandled state:  eventType=" + event.getType() + "; eventState=" + eventState);
        }
        break;
    default:
        logger.warn("Unhandled event type:  eventType=" + event.getType() + "; eventState=" + event.getState());
    }

}

From source file:io.s4.comm.core.DefaultWatcher.java

License:Open Source License

synchronized public void process(WatchedEvent event) {
    logger.info("Received zk event:" + event);
    synchronized (mutex) {
        currentEvent = event;//from   w w w.  ja  v a 2 s  . c  o m
        if (event.getState() == KeeperState.SyncConnected) {
            connected = true;
        }
        if (callbackHandler != null && interestingStates.contains(event.getState())) {
            Map<String, Object> eventData = new HashMap<String, Object>();
            if (event.getState() == KeeperState.SyncConnected) {
                eventData.put("state", CommLayerState.INITIALIZED);
            } else if (event.getState() == KeeperState.Expired) {
                eventData.put("state", CommLayerState.BROKEN);
            }
            eventData.put("source", event);
            callbackHandler.handleCallback(eventData);
        }
        mutex.notify();
    }
}

From source file:io.seldon.api.state.ZkABTestingUpdater.java

License:Apache License

@Override
public void run() {
    logger.info("Starting");
    try {//from w  ww.  ja v a  2  s  . co m
        while (keepRunning) {
            boolean error = false;
            try {

                CuratorFramework client = null;
                boolean ok = false;
                for (int attempts = 0; attempts < 4 && !ok; attempts++) {
                    client = curatorHandler.getCurator().usingNamespace(clientName);
                    logger.info("Waiting until zookeeper connected");
                    ok = client.getZookeeperClient().blockUntilConnectedOrTimedOut();
                    if (ok)
                        logger.info("zookeeper connected on attempt " + attempts);
                    else {
                        logger.error("Timed out waiting for zookeeper connect : attempt " + attempts);
                    }
                }
                if (!ok) {
                    logger.error("Failed to connect to zookeeper after multiple attempts - STOPPING");
                    return;
                }
                queue = new LinkedBlockingQueue<>();
                Watcher watcher = new Watcher() {
                    boolean expired;

                    @Override
                    public void process(WatchedEvent event) {
                        try {
                            if (event.getPath() != null)
                                queue.put(event.getPath());
                            else {
                                logger.warn("Unexpected event " + event.getType().name() + " -> "
                                        + event.toString());
                                switch (event.getState()) {
                                case SyncConnected: {
                                }
                                    break;
                                case Expired: {
                                    queue.put("");
                                }
                                    break;
                                case Disconnected: {
                                }
                                    break;
                                }
                            }
                        } catch (InterruptedException e) {
                            throw new Error(e);
                        }
                    }
                };

                logger.info("Checking path " + DYNAMIC_PARAM_PATH + " exists");
                if (client.checkExists().forPath(DYNAMIC_PARAM_PATH) == null) {
                    logger.warn("Path " + DYNAMIC_PARAM_PATH + " does not exist for client " + clientName
                            + " creating...");
                    client.create().forPath(DYNAMIC_PARAM_PATH);
                }

                logger.info("Checking path " + AB_ALG_PATH + " exists");
                if (client.checkExists().forPath(AB_ALG_PATH) == null) {
                    logger.warn("Path " + AB_ALG_PATH + " does not exist for client " + clientName
                            + " creating...");
                    client.create().forPath(AB_ALG_PATH);
                }

                client.getData().usingWatcher(watcher).forPath(DYNAMIC_PARAM_PATH);
                client.getData().usingWatcher(watcher).forPath(AB_ALG_PATH);

                boolean restart = false;
                while (keepRunning && !restart) {

                    String path = queue.take();
                    if (!StringUtils.isEmpty(path)) {
                        logger.info("Alg Path changed " + path);

                        System.out.println("Alg Path changed " + path);

                        if (path.endsWith(DYNAMIC_PARAM_PATH)) {
                            try {
                                byte[] bytes = client.getData().forPath(DYNAMIC_PARAM_PATH);
                                ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes));
                                DynamicParameterBean bean = (DynamicParameterBean) in.readObject();
                                in.close();
                                logger.info("Updating dynamic parameter: " + bean.getName()
                                        + " and setting to value: " + bean.getValue() + " for client "
                                        + clientName);
                                DynamicParameterServer.setParameterBean(clientName, bean);
                                numUpdates++;
                            } catch (ClassNotFoundException e) {
                                logger.error("Can't find class ", e);
                            } catch (IOException e) {
                                logger.error("Failed to deserialize algorithm for client " + clientName, e);
                            } finally {
                                client.getData().usingWatcher(watcher).forPath(DYNAMIC_PARAM_PATH);
                            }

                        } else if (path.endsWith(AB_ALG_PATH)) {
                            try {
                                byte[] bytes = client.getData().forPath(AB_ALG_PATH);

                                ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes));
                                ABTest abTest = (ABTest) in.readObject();
                                in.close();
                                logger.info("Updating Algorithm percentage for client " + clientName + " to "
                                        + abTest.toString());
                                ABTestingServer.setABTest(clientName, abTest);
                                numUpdates++;
                            } catch (ClassNotFoundException e) {
                                logger.error("Can't find class ", e);
                            } catch (IOException e) {
                                logger.error("Failed to deserialize algorithm for client " + clientName, e);
                            } finally {
                                client.getData().usingWatcher(watcher).forPath(AB_ALG_PATH);
                            }
                        } else {
                            logger.error("Unknown path " + path + " changed so reseting watchers");
                        }
                    } else {
                        //client.getData().usingWatcher(watcher).forPath(DYNAMIC_PARAM_PATH);
                        //client.getData().usingWatcher(watcher).forPath(AB_ALG_PATH);
                        logger.warn("Will try to restart");
                        restart = true;
                    }

                }

            } catch (IOException e) {
                logger.error("Exception trying to create sk client ", e);
                error = true;
            } catch (Exception e) {
                logger.error("Exception from zookeeper client ", e);
                error = true;
            } finally {

            }

            if (keepRunning && error) {
                logger.info("Sleeping " + sleepTime);
                Thread.sleep(sleepTime);
                if (sleepTime * 2 < maxSleepTime)
                    sleepTime = sleepTime * 2;
                error = false;
            }

        }
    } catch (InterruptedException e) {
        logger.warn("Sleep interuppted ", e);
    }
    logger.info("Stopping");
}

From source file:io.seldon.api.state.ZkAlgorithmUpdater.java

License:Apache License

@Override
public void run() {
    logger.info("Starting");
    try {/*from w  w w .ja va  2  s  .  co  m*/
        boolean error = false;
        while (keepRunning) {
            try {

                CuratorFramework client = null;
                boolean ok = false;
                for (int attempts = 0; attempts < 4 && !ok; attempts++) {
                    client = curatorHandler.getCurator().usingNamespace(clientName);
                    logger.info("Waiting until zookeeper connected on attempt " + attempts);
                    ok = client.getZookeeperClient().blockUntilConnectedOrTimedOut();
                    if (ok)
                        logger.info("zookeeper connected");
                    else {
                        logger.error("Timed out waiting for zookeeper connect : attempt " + attempts);
                    }
                }
                if (!ok) {
                    logger.error("Failed to connect to zookeeper after multiple attempts - STOPPING");
                    return;
                }
                queue = new LinkedBlockingQueue<>();
                final Watcher watcher = new Watcher() {
                    boolean expired = false;

                    @Override
                    public void process(WatchedEvent event) {
                        try {
                            if (event.getPath() != null)
                                queue.put(event.getPath());
                            else {
                                logger.warn("Unexpected event " + event.getType().name() + " -> "
                                        + event.toString());
                                switch (event.getState()) {
                                case SyncConnected: {
                                }
                                    break;
                                case Expired: {
                                    queue.put("");
                                }
                                    break;
                                case Disconnected: {
                                    logger.warn("Disconnected from server");
                                    //queue.put("");                                      
                                }
                                    break;
                                }

                            }
                        } catch (InterruptedException e) {
                            throw new Error(e);
                        }
                    }
                };

                logger.info("Checking path " + ALG_PATH + " exists");
                if (client.checkExists().forPath(ALG_PATH) == null) {
                    logger.warn(
                            "Path " + ALG_PATH + " does not exist for client " + clientName + " creating...");
                    client.create().forPath(ALG_PATH);
                } else
                    logger.info("Path " + ALG_PATH + " exists");

                //client.getConnectionStateListenable().addListener(stateListener);
                boolean restart = false;
                while (keepRunning && !restart) {

                    client.getData().usingWatcher(watcher).forPath(ALG_PATH);

                    String path = queue.take();
                    if (!StringUtils.isEmpty(path)) {
                        logger.info("Alg Path changed " + path);

                        byte[] bytes = client.getData().forPath(ALG_PATH);

                        try {
                            ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes));
                            CFAlgorithm alg = (CFAlgorithm) in.readObject();
                            in.close();
                            //Update Algorithm for client
                            logger.info(
                                    "Updating algorithm options for " + clientName + " to " + alg.toString());
                            Util.getAlgorithmService().setAlgorithmOptions(clientName, alg);
                            numUpdates++;
                        } catch (ClassNotFoundException e) {
                            logger.error("Can't find class ", e);
                        } catch (IOException e) {
                            logger.error("Failed to deserialize algorithm for client " + clientName, e);
                        }
                    } else {
                        //logger.warn("Empty path - maybe zookeeper connection state change watcher will be reset");
                        logger.warn("Will try to restart");
                        restart = true;
                    }
                }

            } catch (IOException e) {
                logger.error("Exception trying to create sk client ", e);
                error = true;
            } catch (Exception e) {
                logger.error("Exception from zookeeper client ", e);
                error = true;
            } finally {

            }

            if (keepRunning && error) {
                logger.info("Sleeping " + sleepTime);
                Thread.sleep(sleepTime);
                if (sleepTime * 2 < maxSleepTime)
                    sleepTime = sleepTime * 2;
                error = false;
            }

        }
    } catch (InterruptedException e) {
        logger.warn("Sleep interuppted ", e);
    }
    logger.info("Stopping");
}

From source file:io.teknek.daemon.Worker.java

License:Apache License

@Override
public void process(WatchedEvent event) {
    logger.debug("recived event " + event);
    if (event.getState() == KeeperState.Expired || event.getState() == KeeperState.Disconnected) {
        driver.setGoOn(false);//  w w w. j av  a  2  s.c om
        shutdown();
    }
    if (event.getType() == EventType.NodeDataChanged || event.getType() == EventType.NodeDeleted) {
        driver.setGoOn(false);
        shutdown();
    }
}

From source file:lab.examples.zookeeper.demo.ZooKeeperConnector.java

License:Apache License

public void init() throws Exception {
    if (hosts == null) {
        throw new IllegalArgumentException(
                "No hosts set for the ZookeeperConnector. Zookeeper connection cannot be created.");
    }//from   w w w.  j  a v  a2  s. c o m

    zooKeeper = new ZooKeeper(hosts, // ZooKeeper service hosts
            15000, // Session timeout in milliseconds                
            new Watcher() { // Anonymous Watcher Object
                @Override
                public void process(WatchedEvent event) {
                    // release lock if ZooKeeper is connected.
                    if (event.getState() == KeeperState.SyncConnected) {
                        connectedSignal.countDown();
                    }
                }
            });
    connectedSignal.await();
}

From source file:mazewar.Mazewar.java

License:Open Source License

/**
 * The place where all the pieces are put together.
 *///from  w w  w. j a v a 2 s . c o  m
public Mazewar(String zkServer, int zkPort, int port, String name, String game, boolean robot) {
    super("ECE419 Mazewar");
    consolePrintLn("ECE419 Mazewar started!");

    /* Set up parent */
    ZK_PARENT += game;

    // Throw up a dialog to get the GUIClient name.
    if (name != null) {
        clientId = name;
    } else {
        clientId = JOptionPane.showInputDialog("Enter your name");
    }
    if ((clientId == null) || (clientId.length() == 0)) {
        Mazewar.quit();
    }

    /* Connect to ZooKeeper and get sequencer details */
    List<ClientNode> nodeList = null;
    try {
        zkWatcher = new ZkWatcher();
        zkConnected = new CountDownLatch(1);
        zooKeeper = new ZooKeeper(zkServer + ":" + zkPort, ZK_TIMEOUT, new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                /* Release Lock if ZooKeeper is connected */
                if (event.getState() == SyncConnected) {
                    zkConnected.countDown();
                } else {
                    System.err.println("Could not connect to ZooKeeper!");
                    System.exit(0);
                }
            }
        });
        zkConnected.await();

        /* Successfully connected, now create our node on ZooKeeper */
        zooKeeper.create(Joiner.on('/').join(ZK_PARENT, clientId),
                Joiner.on(':').join(InetAddress.getLocalHost().getHostAddress(), port).getBytes(),
                ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);

        /* Get Seed from Parent */
        mazeSeed = Long.parseLong(new String(zooKeeper.getData(ZK_PARENT, false, null)));

        /* Initialize Sequence Number */
        sequenceNumber = new AtomicInteger(zooKeeper.exists(ZK_PARENT, false).getVersion());

        /* Get list of nodes */
        nodeList = ClientNode.sortList(zooKeeper.getChildren(ZK_PARENT, false));
    } catch (Exception e) {
        e.printStackTrace();
        System.exit(1);
    }

    // Create the maze
    maze = new MazeImpl(new Point(mazeWidth, mazeHeight), mazeSeed);
    assert (maze != null);

    // Have the ScoreTableModel listen to the maze to find
    // out how to adjust scores.
    ScoreTableModel scoreModel = new ScoreTableModel();
    assert (scoreModel != null);
    maze.addMazeListener(scoreModel);

    /* Initialize packet queue */
    packetQueue = new ArrayBlockingQueue<MazePacket>(QUEUE_SIZE);
    sequencedQueue = new PriorityBlockingQueue<MazePacket>(QUEUE_SIZE, new Comparator<MazePacket>() {
        @Override
        public int compare(MazePacket o1, MazePacket o2) {
            return o1.sequenceNumber.compareTo(o2.sequenceNumber);
        }
    });

    /* Inject Event Bus into Client */
    Client.setEventBus(eventBus);

    /* Initialize ZMQ Context */
    context = ZMQ.context(2);

    /* Set up publisher */
    publisher = context.socket(ZMQ.PUB);
    publisher.bind("tcp://*:" + port);
    System.out.println("ZeroMQ Publisher Bound On: " + port);

    try {
        Thread.sleep(100);
    } catch (Exception e) {
        e.printStackTrace();
    }

    /* Set up subscriber */
    subscriber = context.socket(ZMQ.SUB);
    subscriber.subscribe(ArrayUtils.EMPTY_BYTE_ARRAY);

    clients = new ConcurrentHashMap<String, Client>();
    try {
        for (ClientNode client : nodeList) {
            if (client.getName().equals(clientId)) {
                clientPath = ZK_PARENT + "/" + client.getPath();
                guiClient = robot ? new RobotClient(clientId) : new GUIClient(clientId);
                clients.put(clientId, guiClient);
                maze.addClient(guiClient);
                eventBus.register(guiClient);
                subscriber.connect("tcp://" + new String(zooKeeper.getData(clientPath, false, null)));
            } else {
                addRemoteClient(client);
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

    checkNotNull(guiClient, "Should have received our clientId in CLIENTS list!");

    // Create the GUIClient and connect it to the KeyListener queue
    this.addKeyListener(guiClient);
    this.isRobot = robot;

    // Use braces to force constructors not to be called at the beginning of the
    // constructor.
    /*{
    maze.addClient(new RobotClient("Norby"));
    maze.addClient(new RobotClient("Robbie"));
    maze.addClient(new RobotClient("Clango"));
    maze.addClient(new RobotClient("Marvin"));
    }*/

    // Create the panel that will display the maze.
    overheadPanel = new OverheadMazePanel(maze, guiClient);
    assert (overheadPanel != null);
    maze.addMazeListener(overheadPanel);

    // Don't allow editing the console from the GUI
    console.setEditable(false);
    console.setFocusable(false);
    console.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder()));

    // Allow the console to scroll by putting it in a scrollpane
    JScrollPane consoleScrollPane = new JScrollPane(console);
    assert (consoleScrollPane != null);
    consoleScrollPane
            .setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Console"));

    // Create the score table
    scoreTable = new JTable(scoreModel);
    assert (scoreTable != null);
    scoreTable.setFocusable(false);
    scoreTable.setRowSelectionAllowed(false);

    // Allow the score table to scroll too.
    JScrollPane scoreScrollPane = new JScrollPane(scoreTable);
    assert (scoreScrollPane != null);
    scoreScrollPane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Scores"));

    // Create the layout manager
    GridBagLayout layout = new GridBagLayout();
    GridBagConstraints c = new GridBagConstraints();
    getContentPane().setLayout(layout);

    // Define the constraints on the components.
    c.fill = GridBagConstraints.BOTH;
    c.weightx = 1.0;
    c.weighty = 3.0;
    c.gridwidth = GridBagConstraints.REMAINDER;
    layout.setConstraints(overheadPanel, c);
    c.gridwidth = GridBagConstraints.RELATIVE;
    c.weightx = 2.0;
    c.weighty = 1.0;
    layout.setConstraints(consoleScrollPane, c);
    c.gridwidth = GridBagConstraints.REMAINDER;
    c.weightx = 1.0;
    layout.setConstraints(scoreScrollPane, c);

    // Add the components
    getContentPane().add(overheadPanel);
    getContentPane().add(consoleScrollPane);
    getContentPane().add(scoreScrollPane);

    // Pack everything neatly.
    pack();

    // Let the magic begin.
    setVisible(true);
    overheadPanel.repaint();
    this.requestFocusInWindow();
}

From source file:me.tfeng.play.avro.d2.AvroD2Server.java

License:Apache License

@Override
public void process(WatchedEvent event) {
    if (event.getType() == EventType.NodeDeleted && event.getPath().equals(nodePath)
            || event.getType() == EventType.None && event.getState() == KeeperState.SyncConnected) {
        // If the node is unexpectedly deleted or if ZooKeeper connection is restored, register the
        // server again.
        register();/*from   ww w . j  ava 2 s. c  o  m*/
    }
}