package rocks.inspectit.server.service; import java.sql.Timestamp; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.List; import java.util.Map; import javax.annotation.PostConstruct; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import rocks.inspectit.server.dao.JmxDefinitionDataIdentDao; import rocks.inspectit.server.dao.JmxSensorTypeIdentDao; import rocks.inspectit.server.dao.MethodIdentDao; import rocks.inspectit.server.dao.MethodIdentToSensorTypeDao; import rocks.inspectit.server.dao.MethodSensorTypeIdentDao; import rocks.inspectit.server.dao.PlatformIdentDao; import rocks.inspectit.server.dao.PlatformSensorTypeIdentDao; import rocks.inspectit.server.spring.aop.MethodLog; import rocks.inspectit.server.util.AgentStatusDataProvider; import rocks.inspectit.server.util.PlatformIdentCache; import rocks.inspectit.shared.all.cmr.model.JmxDefinitionDataIdent; import rocks.inspectit.shared.all.cmr.model.JmxSensorTypeIdent; import rocks.inspectit.shared.all.cmr.model.MethodIdent; import rocks.inspectit.shared.all.cmr.model.MethodIdentToSensorType; import rocks.inspectit.shared.all.cmr.model.MethodSensorTypeIdent; import rocks.inspectit.shared.all.cmr.model.PlatformIdent; import rocks.inspectit.shared.all.cmr.model.PlatformSensorTypeIdent; import rocks.inspectit.shared.all.exception.BusinessException; import rocks.inspectit.shared.all.exception.enumeration.AgentManagementErrorCodeEnum; import rocks.inspectit.shared.all.spring.logger.Log; import rocks.inspectit.shared.cs.cmr.service.IRegistrationService; /** * This class is used as a delegator to the real registration service. It is needed because Spring * weaves a proxy around the real registration service which cannot be used in an RMI context with * Java 1.4 (as no pre-generated stub is available). * * @author Patrice Bouillet * */ @Service @Transactional public class RegistrationService implements IRegistrationService { /** The logger of this class. */ @Log Logger log; /** * Should IP addresses be used for agent distinction. */ @Value(value = "${cmr.ipBasedAgentRegistration}") boolean ipBasedAgentRegistration = true; /** * The platform ident DAO. */ @Autowired PlatformIdentDao platformIdentDao; /** * The jmx definition data ident DAO. */ @Autowired JmxDefinitionDataIdentDao jmxDefinitionDataIdentDao; /** * The method ident DAO. */ @Autowired MethodIdentDao methodIdentDao; /** * The method sensor type ident DAO. */ @Autowired MethodSensorTypeIdentDao methodSensorTypeIdentDao; /** * The platform sensor type ident DAO. */ @Autowired PlatformSensorTypeIdentDao platformSensorTypeIdentDao; /** * The jmx sensor type ident DAO. */ @Autowired JmxSensorTypeIdentDao jmxSensorTypeIdentDao; /** * The method ident to sensor type DAO. */ @Autowired MethodIdentToSensorTypeDao methodIdentToSensorTypeDao; /** * {@link AgentStatusDataProvider}. */ @Autowired AgentStatusDataProvider agentStatusDataProvider; /** * {@link PlatformIdentCache} called directly for marking dirty state. */ @Autowired PlatformIdentCache platformIdentCache; /** * {@inheritDoc} */ @Override @MethodLog public synchronized long registerPlatformIdent(List<String> definedIPs, String agentName, String version) throws BusinessException { if (log.isInfoEnabled()) { log.info("Trying to register Agent '" + agentName + "'"); } // find existing registered List<PlatformIdent> platformIdentResults; if (ipBasedAgentRegistration) { platformIdentResults = platformIdentDao.findByNameAndIps(agentName, definedIPs); } else { platformIdentResults = platformIdentDao.findByName(agentName); } PlatformIdent platformIdent = new PlatformIdent(); platformIdent.setAgentName(agentName); if (1 == platformIdentResults.size()) { platformIdent = platformIdentResults.get(0); } else if (platformIdentResults.size() > 1) { // this cannot occur anymore, if it occurs, then there is something totally wrong! log.error("More than one platform ident has been retrieved! Please send your Database to the NovaTec inspectIT support!"); throw new BusinessException("Register the agent with name " + agentName + " and following network interfaces " + definedIPs + ".", AgentManagementErrorCodeEnum.MORE_THAN_ONE_AGENT_REGISTERED); } // always update the time stamp and ips, no matter if this is an old or new record. platformIdent.setTimeStamp(new Timestamp(Calendar.getInstance().getTimeInMillis())); platformIdent.setDefinedIPs(definedIPs); // also always update the version information of the agent platformIdent.setVersion(version); platformIdentDao.saveOrUpdate(platformIdent); agentStatusDataProvider.registerConnected(platformIdent.getId()); if (log.isInfoEnabled()) { log.info("Successfully registered the Agent '" + agentName + "' with id " + platformIdent.getId() + ", version " + version + " and following network interfaces:"); printOutDefinedIPs(definedIPs); } return platformIdent.getId(); } /** * {@inheritDoc} * * @throws BusinessException */ @Override @MethodLog public void unregisterPlatformIdent(long platformId) throws BusinessException { log.info("Trying to unregister the Agent with the ID " + platformId); boolean unregistered = agentStatusDataProvider.registerDisconnected(platformId); if (unregistered) { log.info("The Agent with the ID " + platformId + " has been successfully unregistered."); } else { log.warn("No registered agent with given ID exists. Unregistration is aborted."); throw new BusinessException("Unregister the agent with ID " + platformId + ".", AgentManagementErrorCodeEnum.AGENT_DOES_NOT_EXIST); } } /** * {@inheritDoc} */ @Override public void updateMethodIdentTimestamp(long platformId, String packageName, String className) { try { methodIdentDao.updateTimestamps(platformId, packageName, className); } finally { platformIdentCache.markDirty(platformId); } } /** * {@inheritDoc} */ @Override @MethodLog public long registerMethodIdent(long platformId, String packageName, String className, String methodName, List<String> parameterTypes, String returnType, int modifiers) { MethodIdent methodIdent = new MethodIdent(); methodIdent.setPackageName(packageName); methodIdent.setClassName(className); methodIdent.setMethodName(methodName); if (null == parameterTypes) { parameterTypes = Collections.emptyList(); } methodIdent.setParameters(parameterTypes); methodIdent.setReturnType(returnType); methodIdent.setModifiers(modifiers); try { List<Long> methodIdentIds = methodIdentDao.findIdForPlatformIdAndExample(platformId, methodIdent, true); if (1 == methodIdentIds.size()) { return methodIdentIds.get(0).longValue(); } else { PlatformIdent platformIdent = new PlatformIdent(); platformIdent.setId(platformId); methodIdent.setPlatformIdent(platformIdent); methodIdent.setTimeStamp(new Timestamp(Calendar.getInstance().getTimeInMillis())); methodIdentDao.saveOrUpdate(methodIdent); return methodIdent.getId(); } } finally { platformIdentCache.markDirty(platformId); } } /** * {@inheritDoc} */ @Override @MethodLog public long registerMethodSensorTypeIdent(long platformId, String fullyQualifiedClassName, Map<String, Object> parameters) { MethodSensorTypeIdent methodSensorTypeIdent; try { List<Long> methodSensorTypeIdents = methodSensorTypeIdentDao.findIdByClassNameAndPlatformId(fullyQualifiedClassName, platformId); if (1 == methodSensorTypeIdents.size()) { Long id = methodSensorTypeIdents.get(0); methodSensorTypeIdentDao.updateParameters(id, parameters); return id; } else { // only if the new sensor is registered we need to update the platform ident PlatformIdent platformIdent = new PlatformIdent(); platformIdent.setId(platformId); methodSensorTypeIdent = new MethodSensorTypeIdent(); methodSensorTypeIdent.setPlatformIdent(platformIdent); methodSensorTypeIdent.setFullyQualifiedClassName(fullyQualifiedClassName); methodSensorTypeIdent.setSettings(parameters); methodSensorTypeIdentDao.saveOrUpdate(methodSensorTypeIdent); return methodSensorTypeIdent.getId(); } } finally { platformIdentCache.markDirty(platformId); } } /** * {@inheritDoc} */ @Override @MethodLog public void addSensorTypeToMethod(long platformId, long methodSensorTypeId, long methodId) { try { Long id = methodIdentToSensorTypeDao.findId(methodId, methodSensorTypeId, true); if (null == id) { MethodIdent methodIdent = new MethodIdent(); methodIdent.setId(methodId); MethodSensorTypeIdent methodSensorTypeIdent = new MethodSensorTypeIdent(); methodSensorTypeIdent.setId(methodSensorTypeId); MethodIdentToSensorType methodIdentToSensorType = new MethodIdentToSensorType(methodIdent, methodSensorTypeIdent, null); methodIdentToSensorType.setTimestamp(new Timestamp(Calendar.getInstance().getTimeInMillis())); methodIdentToSensorTypeDao.saveOrUpdate(methodIdentToSensorType); } } finally { platformIdentCache.markDirty(platformId); } } /** * {@inheritDoc} */ @Override @MethodLog public long registerPlatformSensorTypeIdent(long platformId, String fullyQualifiedClassName) { try { List<Long> platformSensorTypeIdentIds = platformSensorTypeIdentDao.findIdByClassNameAndPlatformId(fullyQualifiedClassName, platformId); if (1 == platformSensorTypeIdentIds.size()) { return platformSensorTypeIdentIds.get(0).longValue(); } else { // only if it s not registered we need updating PlatformIdent platformIdent = new PlatformIdent(); platformIdent.setId(platformId); PlatformSensorTypeIdent platformSensorTypeIdent = new PlatformSensorTypeIdent(); platformSensorTypeIdent.setPlatformIdent(platformIdent); platformSensorTypeIdent.setFullyQualifiedClassName(fullyQualifiedClassName); platformSensorTypeIdentDao.saveOrUpdate(platformSensorTypeIdent); return platformSensorTypeIdent.getId(); } } finally { platformIdentCache.markDirty(platformId); } } /** * {@inheritDoc} */ @Override @Transactional @MethodLog public long registerJmxSensorTypeIdent(long platformId, String fullyQualifiedClassName) { JmxSensorTypeIdent jmxSensorTypeIdent = new JmxSensorTypeIdent(); jmxSensorTypeIdent.setFullyQualifiedClassName(fullyQualifiedClassName); try { List<Long> jmxSensorTypeIdents = jmxSensorTypeIdentDao.findIdByExample(platformId, jmxSensorTypeIdent); if (1 == jmxSensorTypeIdents.size()) { return jmxSensorTypeIdents.get(0).longValue(); } else { PlatformIdent platformIdent = new PlatformIdent(); platformIdent.setId(platformId); jmxSensorTypeIdent.setPlatformIdent(platformIdent); jmxSensorTypeIdentDao.saveOrUpdate(jmxSensorTypeIdent); return jmxSensorTypeIdent.getId(); } } finally { platformIdentCache.markDirty(platformId); } } /** * {@inheritDoc} */ @Override @Transactional @MethodLog public long registerJmxSensorDefinitionDataIdent(long platformId, String mBeanObjectName, String mBeanAttributeName, String mBeanAttributeDescription, String mBeanAttributeType, boolean isIs, // NOCHK boolean isReadable, boolean isWritable) { JmxDefinitionDataIdent jmxDefinitionDataIdent = new JmxDefinitionDataIdent(); jmxDefinitionDataIdent.setmBeanObjectName(mBeanObjectName); jmxDefinitionDataIdent.setmBeanAttributeName(mBeanAttributeName); jmxDefinitionDataIdent.setmBeanAttributeDescription(mBeanAttributeDescription); jmxDefinitionDataIdent.setmBeanAttributeType(mBeanAttributeType); jmxDefinitionDataIdent.setmBeanAttributeIsIs(isIs); jmxDefinitionDataIdent.setmBeanAttributeIsReadable(isReadable); jmxDefinitionDataIdent.setmBeanAttributeIsWritable(isWritable); try { List<Long> ids = jmxDefinitionDataIdentDao.findIdForPlatformIdent(platformId, jmxDefinitionDataIdent, true); if (1 == ids.size()) { return ids.get(0).longValue(); } else { PlatformIdent platformIdent = new PlatformIdent(); platformIdent.setId(platformId); jmxDefinitionDataIdent.setPlatformIdent(platformIdent); jmxDefinitionDataIdent.setTimeStamp(new Timestamp(Calendar.getInstance().getTimeInMillis())); jmxDefinitionDataIdentDao.saveOrUpdate(jmxDefinitionDataIdent); return jmxDefinitionDataIdent.getId(); } } finally { platformIdentCache.markDirty(platformId); } } /** * Prints out the given list of defined IP addresses. The example is: * <p> * |- IPv4: 192.168.1.6<br> * |- IPv4: 127.0.0.1<br> * |- IPv6: fe80:0:0:0:221:5cff:fe1d:ffdf%3<br> * |- IPv6: 0:0:0:0:0:0:0:1%1 * * @param definedIPs * List of IPv4 and IPv6 IPs. */ private void printOutDefinedIPs(List<String> definedIPs) { List<String> ipList = new ArrayList<>(); for (String ip : definedIPs) { if (ip.indexOf(':') != -1) { ipList.add("|- IPv6: " + ip); } else { ipList.add("|- IPv4: " + ip); } } Collections.sort(ipList); for (String ip : ipList) { log.info(ip); } } /** * Is executed after dependency injection is done to perform any initialization. */ @PostConstruct public void postConstruct() { if (log.isInfoEnabled()) { log.info("|-Registration Service active..."); } } }