/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.portal.kernel.resiliency.spi.agent.annotation; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.LinkedList; import java.util.Map; import java.util.Queue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; /** * @author Shuyang Zhou */ public class DistributedRegistry { public static boolean isDistributed(String name, Direction direction) { Direction registeredDirection = _exactDirections.get(name); if ((registeredDirection == direction) || (registeredDirection == Direction.DUPLEX)) { return true; } if (registeredDirection != null) { return false; } for (Map.Entry<String, Direction> entry : _postfixDirections.entrySet()) { String postfix = entry.getKey(); if (name.endsWith(postfix)) { registeredDirection = entry.getValue(); if ((registeredDirection == direction) || (registeredDirection == Direction.DUPLEX)) { return true; } } } for (Map.Entry<String, Direction> entry : _prefixDirections.entrySet()) { String prefix = entry.getKey(); if (name.startsWith(prefix)) { registeredDirection = entry.getValue(); if ((registeredDirection == direction) || (registeredDirection == Direction.DUPLEX)) { return true; } } } return false; } public static void registerDistributed(Class<?> clazz) { processDistributed(clazz, true); } public static void registerDistributed( String name, Direction direction, MatchType matchType) { if (matchType.equals(MatchType.POSTFIX)) { _postfixDirections.put(name, direction); } else if (matchType.equals(MatchType.PREFIX)) { _prefixDirections.put(name, direction); } else { _exactDirections.put(name, direction); } } public static void unregisterDistributed(Class<?> clazz) { processDistributed(clazz, false); } public static boolean unregisterDistributed( String name, Direction direction, MatchType matchType) { if (matchType.equals(MatchType.POSTFIX)) { if (direction == null) { direction = _postfixDirections.remove(name); if (direction != null) { return true; } return false; } return _postfixDirections.remove(name, direction); } else if (matchType.equals(MatchType.PREFIX)) { if (direction == null) { direction = _prefixDirections.remove(name); if (direction != null) { return true; } return false; } return _prefixDirections.remove(name, direction); } else { if (direction == null) { direction = _exactDirections.remove(name); if (direction != null) { return true; } return false; } return _exactDirections.remove(name, direction); } } protected static void processDistributed(Class<?> clazz, boolean register) { Queue<Class<?>> queue = new LinkedList<>(); queue.offer(clazz); Class<?> currentClass = null; while ((currentClass = queue.poll()) != null) { Field[] fields = currentClass.getDeclaredFields(); for (Field field : fields) { Distributed distributed = field.getAnnotation( Distributed.class); if (distributed == null) { continue; } int modifiers = field.getModifiers(); if (!Modifier.isPublic(modifiers) || !Modifier.isStatic(modifiers) || !Modifier.isFinal(modifiers) || (field.getType() != String.class)) { continue; } try { String name = (String)field.get(null); if (register) { registerDistributed( name, distributed.direction(), distributed.matchType()); } else { unregisterDistributed( name, distributed.direction(), distributed.matchType()); } } catch (Throwable t) { throw new RuntimeException(t); } } Class<?> supperClass = currentClass.getSuperclass(); if ((supperClass != null) && (supperClass != Object.class)) { queue.offer(supperClass); } Class<?>[] interfaceClasses = currentClass.getInterfaces(); for (Class<?> interfaceClass : interfaceClasses) { if (!queue.contains(interfaceClass)) { queue.offer(interfaceClass); } } } } private static final ConcurrentMap<String, Direction> _exactDirections = new ConcurrentHashMap<>(); private static final ConcurrentMap<String, Direction> _postfixDirections = new ConcurrentHashMap<>(); private static final ConcurrentMap<String, Direction> _prefixDirections = new ConcurrentHashMap<>(); }