001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.kernel.resiliency.spi.agent.annotation;
016    
017    import java.lang.reflect.Field;
018    import java.lang.reflect.Modifier;
019    
020    import java.util.LinkedList;
021    import java.util.Map;
022    import java.util.Queue;
023    import java.util.concurrent.ConcurrentHashMap;
024    import java.util.concurrent.ConcurrentMap;
025    
026    /**
027     * @author Shuyang Zhou
028     */
029    public class DistributedRegistry {
030    
031            public static boolean isDistributed(String name, Direction direction) {
032                    Direction registeredDirection = _exactDirections.get(name);
033    
034                    if ((registeredDirection == direction) ||
035                            (registeredDirection == Direction.DUPLEX)) {
036    
037                            return true;
038                    }
039    
040                    if (registeredDirection != null) {
041                            return false;
042                    }
043    
044                    for (Map.Entry<String, Direction> entry :
045                                    _postfixDirections.entrySet()) {
046    
047                            String postfix = entry.getKey();
048    
049                            if (name.endsWith(postfix)) {
050                                    registeredDirection = entry.getValue();
051    
052                                    if ((registeredDirection == direction) ||
053                                            (registeredDirection == Direction.DUPLEX)) {
054    
055                                            return true;
056                                    }
057                            }
058                    }
059    
060                    for (Map.Entry<String, Direction> entry :
061                                    _prefixDirections.entrySet()) {
062    
063                            String prefix = entry.getKey();
064    
065                            if (name.startsWith(prefix)) {
066                                    registeredDirection = entry.getValue();
067    
068                                    if ((registeredDirection == direction) ||
069                                            (registeredDirection == Direction.DUPLEX)) {
070    
071                                            return true;
072                                    }
073                            }
074                    }
075    
076                    return false;
077            }
078    
079            public static void registerDistributed(Class<?> clazz) {
080                    processDistributed(clazz, true);
081            }
082    
083            public static void registerDistributed(
084                    String name, Direction direction, MatchType matchType) {
085    
086                    if (matchType.equals(MatchType.POSTFIX)) {
087                            _postfixDirections.put(name, direction);
088                    }
089                    else if (matchType.equals(MatchType.PREFIX)) {
090                            _prefixDirections.put(name, direction);
091                    }
092                    else {
093                            _exactDirections.put(name, direction);
094                    }
095            }
096    
097            public static void unregisterDistributed(Class<?> clazz) {
098                    processDistributed(clazz, false);
099            }
100    
101            public static boolean unregisterDistributed(
102                    String name, Direction direction, MatchType matchType) {
103    
104                    if (matchType.equals(MatchType.POSTFIX)) {
105                            if (direction == null) {
106                                    direction = _postfixDirections.remove(name);
107    
108                                    return direction != null;
109                            }
110    
111                            return _postfixDirections.remove(name, direction);
112                    }
113                    else if (matchType.equals(MatchType.PREFIX)) {
114                            if (direction == null) {
115                                    direction = _prefixDirections.remove(name);
116    
117                                    return direction != null;
118                            }
119    
120                            return _prefixDirections.remove(name, direction);
121                    }
122                    else {
123                            if (direction == null) {
124                                    direction = _exactDirections.remove(name);
125    
126                                    return direction != null;
127                            }
128    
129                            return _exactDirections.remove(name, direction);
130                    }
131            }
132    
133            protected static void processDistributed(Class<?> clazz, boolean register) {
134                    Queue<Class<?>> queue = new LinkedList<Class<?>>();
135    
136                    queue.offer(clazz);
137    
138                    Class<?> currentClass = null;
139    
140                    while ((currentClass = queue.poll()) != null) {
141                            Field[] fields = currentClass.getDeclaredFields();
142    
143                            for (Field field : fields) {
144                                    Distributed distributed = field.getAnnotation(
145                                            Distributed.class);
146    
147                                    if (distributed == null) {
148                                            continue;
149                                    }
150    
151                                    int modifiers = field.getModifiers();
152    
153                                    if (!Modifier.isPublic(modifiers) ||
154                                            !Modifier.isStatic(modifiers) ||
155                                            !Modifier.isFinal(modifiers) ||
156                                            (field.getType() != String.class)) {
157    
158                                            continue;
159                                    }
160    
161                                    try {
162                                            String name = (String)field.get(null);
163    
164                                            if (register) {
165                                                    registerDistributed(
166                                                            name, distributed.direction(),
167                                                            distributed.matchType());
168                                            }
169                                            else {
170                                                    unregisterDistributed(
171                                                            name, distributed.direction(),
172                                                            distributed.matchType());
173                                            }
174                                    }
175                                    catch (Throwable t) {
176                                            throw new RuntimeException(t);
177                                    }
178                            }
179    
180                            Class<?> supperClass = currentClass.getSuperclass();
181    
182                            if ((supperClass != null) && (supperClass != Object.class)) {
183                                    queue.offer(supperClass);
184                            }
185    
186                            Class<?>[] interfaceClasses = currentClass.getInterfaces();
187    
188                            for (Class<?> interfaceClass : interfaceClasses) {
189                                    if (!queue.contains(interfaceClass)) {
190                                            queue.offer(interfaceClass);
191                                    }
192                            }
193                    }
194            }
195    
196            private static ConcurrentMap<String, Direction> _exactDirections =
197                    new ConcurrentHashMap<String, Direction>();
198            private static ConcurrentMap<String, Direction> _postfixDirections =
199                    new ConcurrentHashMap<String, Direction>();
200            private static ConcurrentMap<String, Direction> _prefixDirections =
201                    new ConcurrentHashMap<String, Direction>();
202    
203    }