001/*
002 * #%L
003 * Netarchivesuite - monitor
004 * %%
005 * Copyright (C) 2005 - 2014 The Royal Danish Library, the Danish State and University Library,
006 *             the National Library of France and the Austrian National Library.
007 * %%
008 * This program is free software: you can redistribute it and/or modify
009 * it under the terms of the GNU Lesser General Public License as
010 * published by the Free Software Foundation, either version 2.1 of the
011 * License, or (at your option) any later version.
012 * 
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016 * GNU General Lesser Public License for more details.
017 * 
018 * You should have received a copy of the GNU General Lesser Public
019 * License along with this program.  If not, see
020 * <http://www.gnu.org/licenses/lgpl-2.1.html>.
021 * #L%
022 */
023
024package dk.netarkivet.monitor.jmx;
025
026import java.util.HashMap;
027import java.util.Map;
028
029import dk.netarkivet.common.exceptions.ArgumentNotValid;
030
031/** Adds caching to another JMXProxyFactoryConnectionFactory. */
032public class CachingProxyConnectionFactory implements JMXProxyConnectionFactory {
033    /** The JMXProxyFactoryConnectionFactory, this class acts as a cache for. */
034    private final JMXProxyConnectionFactory wrappedFactory;
035
036    /**
037     * Encapsulates the unit of information for checking the cache. That is, all information used as arguments for the
038     * JMXProxyFactoryConnectionFactory.getConnection method.
039     */
040    static class CacheKey {
041        String server;
042        int port, rmiPort;
043        String userName, password;
044
045        /**
046         * Constructor for this class.
047         *
048         * @param server The server name.
049         * @param port The JMX port number.
050         * @param rmiPort The RMI callback number.
051         * @param userName The JMX user name.
052         * @param password The JMX password.
053         */
054        public CacheKey(String server, int port, int rmiPort, String userName, String password) {
055            this.server = server;
056            this.port = port;
057            this.rmiPort = rmiPort;
058            this.userName = userName;
059            this.password = password;
060        }
061
062        /**
063         * Equals method, that overrides the Object.equals method.
064         *
065         * @param o anObject
066         * @return true, if o is equal to this object; else false
067         * @see Object#equals(java.lang.Object)
068         */
069        public boolean equals(Object o) {
070            if (this == o) {
071                return true;
072            }
073            if (o == null || getClass() != o.getClass()) {
074                return false;
075            }
076
077            CacheKey cacheKey = (CacheKey) o;
078
079            if (port != cacheKey.port) {
080                return false;
081            }
082            if (rmiPort != cacheKey.rmiPort) {
083                return false;
084            }
085            if (!password.equals(cacheKey.password)) {
086                return false;
087            }
088            if (!server.equals(cacheKey.server)) {
089                return false;
090            }
091            if (!userName.equals(cacheKey.userName)) {
092                return false;
093            }
094
095            return true;
096        }
097
098        /**
099         * hashCode method, that overrides the Object.hashCode method.
100         *
101         * @return the hashcode for this object
102         * @see Object#hashCode()
103         */
104        public int hashCode() {
105            int result;
106            result = server.hashCode();
107            result = 31 * result + port;
108            result = 31 * result + rmiPort;
109            result = 31 * result + userName.hashCode();
110            result = 31 * result + password.hashCode();
111            return result;
112        }
113    }
114
115    private Map<CacheKey, JMXProxyConnection> cache = new HashMap<CacheKey, JMXProxyConnection>();
116
117    /**
118     * Registers the factory to wrap and initializes connection cache.
119     *
120     * @param wrappedFactory The factory to add caching to.
121     */
122    public CachingProxyConnectionFactory(JMXProxyConnectionFactory wrappedFactory) {
123        this.wrappedFactory = wrappedFactory;
124    }
125
126    /**
127     * If (server,port,userName) has been seen before, looks up the cached connection associated with these values.
128     * Otherwise passes the request on the the wrapped factory, caching the result for future reuse.
129     *
130     * @see JMXProxyConnectionFactory#getConnection(String, int, int, String, String)
131     */
132    public JMXProxyConnection getConnection(String server, int port, int rmiPort, String userName, String password) {
133        ArgumentNotValid.checkNotNullOrEmpty(server, "server");
134        ArgumentNotValid.checkNotNullOrEmpty(userName, "userName");
135        ArgumentNotValid.checkNotNullOrEmpty(password, "password");
136        CacheKey key = new CacheKey(server, port, rmiPort, userName, password);
137        if (cache.containsKey(key)) {
138            JMXProxyConnection jmxProxyConnection = cache.get(key);
139            if (jmxProxyConnection != null && jmxProxyConnection.isLive()) {
140                return jmxProxyConnection;
141            }
142        }
143        JMXProxyConnection newConnection = wrappedFactory.getConnection(server, port, rmiPort, userName, password);
144        cache.put(key, newConnection);
145        return newConnection;
146    }
147
148}