/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.apache.zookeeper.server.jersey; import java.io.IOException; import java.util.HashMap; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.ZooKeeper; import org.apache.zookeeper.Watcher.Event.KeeperState; /** * Singleton which provides JAX-RS resources access to the ZooKeeper * client. There's a single session for each base uri (so usually just one). */ public class ZooKeeperService { /** Map base uri to ZooKeeper host:port parameters */ private static HashMap<String, String> uriMap = new HashMap<String, String>(); /** Map base uri to ZooKeeper session */ private static HashMap<String, ZooKeeper> zkMap = new HashMap<String, ZooKeeper>(); /** Track the status of the ZooKeeper session */ private static class MyWatcher implements Watcher { volatile boolean connected; final String uriBase; /** Separate watcher for each base uri */ public MyWatcher(String uriBase) { this.uriBase = uriBase; } /** Track state - in particular watch for expiration. if * it happens for re-creation of the ZK client session */ synchronized public void process(WatchedEvent event) { if (event.getState() == KeeperState.SyncConnected) { connected = true; } else if (event.getState() == KeeperState.Expired) { connected = false; close(uriBase); } else { connected = false; } } } /** * Specify ZooKeeper host:port for a particular base uri. The host:port * string is passed to the ZK client, so this can be formatted with * more than a single host:port pair. */ synchronized public static void mapUriBase(String uriBase, String hostport) { uriMap.put(uriBase, hostport); } /** * Close the ZooKeeper session and remove it from the internal maps */ synchronized public static void close(String uriBase) { ZooKeeper zk = zkMap.remove(uriBase); if (zk == null) { return; } try { zk.close(); } catch (InterruptedException e) { // FIXME e.printStackTrace(); } } /** * Return a ZooKeeper client which may or may not be connected, but * it will not be expired. This method can be called multiple times, * the same object will be returned except in the case where the * session expires (at which point a new session will be returned) */ synchronized public static ZooKeeper getClient(String baseUri) throws IOException { ZooKeeper zk = zkMap.get(baseUri); if (zk == null) { String hostPort = uriMap.get(baseUri); zk = new ZooKeeper(hostPort, 30000, new MyWatcher(baseUri)); zkMap.put(baseUri, zk); } return zk; } }