/* | |
* 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 com.alibaba.dubbo.remoting.zookeeper.support; | |
import com.alibaba.dubbo.common.URL; | |
import com.alibaba.dubbo.common.logger.Logger; | |
import com.alibaba.dubbo.common.logger.LoggerFactory; | |
import com.alibaba.dubbo.remoting.zookeeper.ChildListener; | |
import com.alibaba.dubbo.remoting.zookeeper.StateListener; | |
import com.alibaba.dubbo.remoting.zookeeper.ZookeeperClient; | |
import java.util.List; | |
import java.util.Set; | |
import java.util.concurrent.ConcurrentHashMap; | |
import java.util.concurrent.ConcurrentMap; | |
import java.util.concurrent.CopyOnWriteArraySet; | |
public abstract class AbstractZookeeperClient<TargetChildListener> implements ZookeeperClient { | |
protected static final Logger logger = LoggerFactory.getLogger(AbstractZookeeperClient.class); | |
private final URL url; | |
private final Set<StateListener> stateListeners = new CopyOnWriteArraySet<StateListener>(); | |
private final ConcurrentMap<String, ConcurrentMap<ChildListener, TargetChildListener>> childListeners = new ConcurrentHashMap<String, ConcurrentMap<ChildListener, TargetChildListener>>(); | |
private volatile boolean closed = false; | |
public AbstractZookeeperClient(URL url) { | |
this.url = url; | |
} | |
@Override | |
public URL getUrl() { | |
return url; | |
} | |
@Override | |
public void create(String path, boolean ephemeral) { | |
if (!ephemeral) { | |
if (checkExists(path)) { | |
return; | |
} | |
} | |
int i = path.lastIndexOf('/'); | |
if (i > 0) { | |
create(path.substring(0, i), false); | |
} | |
if (ephemeral) { | |
createEphemeral(path); | |
} else { | |
createPersistent(path); | |
} | |
} | |
@Override | |
public void addStateListener(StateListener listener) { | |
stateListeners.add(listener); | |
} | |
@Override | |
public void removeStateListener(StateListener listener) { | |
stateListeners.remove(listener); | |
} | |
public Set<StateListener> getSessionListeners() { | |
return stateListeners; | |
} | |
@Override | |
public List<String> addChildListener(String path, final ChildListener listener) { | |
ConcurrentMap<ChildListener, TargetChildListener> listeners = childListeners.get(path); | |
if (listeners == null) { | |
childListeners.putIfAbsent(path, new ConcurrentHashMap<ChildListener, TargetChildListener>()); | |
listeners = childListeners.get(path); | |
} | |
TargetChildListener targetListener = listeners.get(listener); | |
if (targetListener == null) { | |
listeners.putIfAbsent(listener, createTargetChildListener(path, listener)); | |
targetListener = listeners.get(listener); | |
} | |
return addTargetChildListener(path, targetListener); | |
} | |
@Override | |
public void removeChildListener(String path, ChildListener listener) { | |
ConcurrentMap<ChildListener, TargetChildListener> listeners = childListeners.get(path); | |
if (listeners != null) { | |
TargetChildListener targetListener = listeners.remove(listener); | |
if (targetListener != null) { | |
removeTargetChildListener(path, targetListener); | |
} | |
} | |
} | |
protected void stateChanged(int state) { | |
for (StateListener sessionListener : getSessionListeners()) { | |
sessionListener.stateChanged(state); | |
} | |
} | |
@Override | |
public void close() { | |
if (closed) { | |
return; | |
} | |
closed = true; | |
try { | |
doClose(); | |
} catch (Throwable t) { | |
logger.warn(t.getMessage(), t); | |
} | |
} | |
protected abstract void doClose(); | |
protected abstract void createPersistent(String path); | |
protected abstract void createEphemeral(String path); | |
protected abstract boolean checkExists(String path); | |
protected abstract TargetChildListener createTargetChildListener(String path, ChildListener listener); | |
protected abstract List<String> addTargetChildListener(String path, TargetChildListener listener); | |
protected abstract void removeTargetChildListener(String path, TargetChildListener listener); | |
} |