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 org.slf4j.Logger; 030import org.slf4j.LoggerFactory; 031 032import dk.netarkivet.common.exceptions.ArgumentNotValid; 033 034/** Adds caching to another JMXProxyFactoryConnectionFactory. */ 035public class CachingProxyConnectionFactory implements JMXProxyConnectionFactory { 036 /** The JMXProxyFactoryConnectionFactory, this class acts as a cache for. */ 037 private final JMXProxyConnectionFactory wrappedFactory; 038 039 /** The log. */ 040 public static final Logger log = LoggerFactory.getLogger(CachingProxyConnectionFactory.class); 041 042 /** 043 * Encapsulates the unit of information for checking the cache. That is, all information used as arguments for the 044 * JMXProxyFactoryConnectionFactory.getConnection method. 045 */ 046 static class CacheKey { 047 String server; 048 int port, rmiPort; 049 String userName, password; 050 051 /** 052 * Constructor for this class. 053 * 054 * @param server The server name. 055 * @param port The JMX port number. 056 * @param rmiPort The RMI callback number. 057 * @param userName The JMX user name. 058 * @param password The JMX password. 059 */ 060 public CacheKey(String server, int port, int rmiPort, String userName, String password) { 061 this.server = server; 062 this.port = port; 063 this.rmiPort = rmiPort; 064 this.userName = userName; 065 this.password = password; 066 } 067 068 /** 069 * Equals method, that overrides the Object.equals method. 070 * 071 * @param o anObject 072 * @return true, if o is equal to this object; else false 073 * @see Object#equals(java.lang.Object) 074 */ 075 public boolean equals(Object o) { 076 if (this == o) { 077 return true; 078 } 079 if (o == null || getClass() != o.getClass()) { 080 return false; 081 } 082 083 CacheKey cacheKey = (CacheKey) o; 084 085 if (port != cacheKey.port) { 086 return false; 087 } 088 if (rmiPort != cacheKey.rmiPort) { 089 return false; 090 } 091 if (!password.equals(cacheKey.password)) { 092 return false; 093 } 094 if (!server.equals(cacheKey.server)) { 095 return false; 096 } 097 if (!userName.equals(cacheKey.userName)) { 098 return false; 099 } 100 101 return true; 102 } 103 104 /** 105 * hashCode method, that overrides the Object.hashCode method. 106 * 107 * @return the hashcode for this object 108 * @see Object#hashCode() 109 */ 110 public int hashCode() { 111 int result; 112 result = server.hashCode(); 113 result = 31 * result + port; 114 result = 31 * result + rmiPort; 115 result = 31 * result + userName.hashCode(); 116 result = 31 * result + password.hashCode(); 117 return result; 118 } 119 } 120 121 private Map<CacheKey, JMXProxyConnection> cache = new HashMap<CacheKey, JMXProxyConnection>(); 122 123 /** 124 * Registers the factory to wrap and initializes connection cache. 125 * 126 * @param wrappedFactory The factory to add caching to. 127 */ 128 public CachingProxyConnectionFactory(JMXProxyConnectionFactory wrappedFactory) { 129 this.wrappedFactory = wrappedFactory; 130 } 131 132 /** 133 * If (server,port,userName) has been seen before, looks up the cached connection associated with these values. 134 * Otherwise passes the request on the the wrapped factory, caching the result for future reuse. 135 * 136 * @see JMXProxyConnectionFactory#getConnection(String, int, int, String, String) 137 */ 138 public JMXProxyConnection getConnection(String server, int port, int rmiPort, String userName, String password) { 139 ArgumentNotValid.checkNotNullOrEmpty(server, "server"); 140 ArgumentNotValid.checkNotNullOrEmpty(userName, "userName"); 141 ArgumentNotValid.checkNotNullOrEmpty(password, "password"); 142 143 CacheKey key = new CacheKey(server, port, rmiPort, userName, password); 144 if (cache.containsKey(key)) { 145 JMXProxyConnection jmxProxyConnection = cache.get(key); 146 if (jmxProxyConnection != null && jmxProxyConnection.isLive()) { 147 log.debug("Retrieving a cached JMXProxyConnection to server {}, port {}, rmiPort {}", server, port, rmiPort); 148 return jmxProxyConnection; 149 } 150 } 151 152 JMXProxyConnection newConnection = wrappedFactory.getConnection(server, port, rmiPort, userName, password); 153 cache.put(key, newConnection); 154 log.info("Caching a new JMXProxyConnection to server {}, port {}, rmiPort {}", server, port, rmiPort); 155 return newConnection; 156 } 157 158}