blob: e5d985060f3180e2f8a3923fb0f54726639ceffb [file] [log] [blame]
/*
* Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// Oracle - initial API and implementation from Oracle TopLink
// @author mobrien
// @since EclipseLink 1.0 enh# 235168
package org.eclipse.persistence.services;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.regex.PatternSyntaxException;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.CompositeType;
import javax.management.openmbean.OpenDataException;
import javax.management.openmbean.OpenType;
import javax.management.openmbean.SimpleType;
import javax.management.openmbean.TabularData;
import javax.management.openmbean.TabularDataSupport;
import javax.management.openmbean.TabularType;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor;
import org.eclipse.persistence.internal.databaseaccess.DatabasePlatform;
import org.eclipse.persistence.internal.databaseaccess.DatasourcePlatform;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.identitymaps.CacheIdentityMap;
import org.eclipse.persistence.internal.identitymaps.CacheKey;
import org.eclipse.persistence.internal.identitymaps.FullIdentityMap;
import org.eclipse.persistence.internal.identitymaps.HardCacheWeakIdentityMap;
import org.eclipse.persistence.internal.identitymaps.IdentityMap;
import org.eclipse.persistence.internal.identitymaps.NoIdentityMap;
import org.eclipse.persistence.internal.identitymaps.SoftCacheWeakIdentityMap;
import org.eclipse.persistence.internal.identitymaps.SoftIdentityMap;
import org.eclipse.persistence.internal.identitymaps.WeakIdentityMap;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.DatabaseSessionImpl;
import org.eclipse.persistence.logging.AbstractSessionLog;
import org.eclipse.persistence.logging.DefaultSessionLog;
import org.eclipse.persistence.logging.JavaLog;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.platform.server.JMXEnabledPlatform;
import org.eclipse.persistence.sessions.DatabaseLogin;
import org.eclipse.persistence.sessions.DefaultConnector;
import org.eclipse.persistence.sessions.Session;
import org.eclipse.persistence.sessions.server.ConnectionPool;
import org.eclipse.persistence.sessions.server.ServerSession;
import org.eclipse.persistence.tools.profiler.PerformanceProfiler;
/**
* <p>
* <b>Purpose</b>: Provide a dynamic interface into the EclipseLink Session.
* <p>
* <b>Description</b>: This class is meant to provide a framework for gaining access to configuration
* of the EclipseLink Session during runtime. It will provide the basis for development
* of a JMX service and possibly other frameworks.
*
*/
public abstract class RuntimeServices {
/** stores access to the session object that we are controlling */
protected Session session;
/** This is the profile weight at server startup time. This is read-only */
private int deployedSessionProfileWeight;
/** This contains the session log from server startup time. This is read-only. */
private SessionLog deployedSessionLog;
public String objectName;
protected static final String EclipseLink_Product_Name = "EclipseLink";
/** Short name for the server platform - Must override in subclass */
protected static String PLATFORM_NAME = "Server";
/**
* Default Constructor
*/
protected RuntimeServices() {
}
/**
* Constructor
* @param session the session to be used with these RuntimeServices
*/
protected RuntimeServices(Session session) {
this.session = session;
}
/**
* INTERNAL:
*/
protected AbstractSession getSession() {
return (AbstractSession)this.session;
}
/**
* Answer the name of the EclipseLink session this MBean represents.
*/
public String getSessionName() {
return getSession().getName();
}
/**
* This method is used to determine if logging is turned on
*/
public boolean getShouldLogMessages() {
return getSession().shouldLogMessages();
}
/**
* This method is used to turn on Performance Profiling
*/
public void setShouldProfilePerformance(boolean shouldProfile) {
if (shouldProfile && (getSession().getProfiler() == null)) {
getSession().setProfiler(new PerformanceProfiler());
} else if (!shouldProfile) {
getSession().setProfiler(null);
}
}
/**
* This method will return if profiling is turned on or not
*/
public boolean getShouldProfilePerformance() {
return (getSession().getProfiler() != null) && ClassConstants.PerformanceProfiler_Class.isAssignableFrom(getSession().getProfiler().getClass());
}
/**
* This method is used to turn on Profile logging when using the Performance Profiler
*/
public void setShouldLogPerformanceProfiler(boolean shouldLogPerformanceProfiler) {
if ((getSession().getProfiler() != null) && ClassConstants.PerformanceProfiler_Class.isAssignableFrom(getSession().getProfiler().getClass())) {
((PerformanceProfiler)getSession().getProfiler()).setShouldLogProfile(shouldLogPerformanceProfiler);
}
}
/**
* Method indicates if Performance profile should be logged
*/
public boolean getShouldLogPerformanceProfiler() {
if ((getSession().getProfiler() != null) && ClassConstants.PerformanceProfiler_Class.isAssignableFrom(getSession().getProfiler().getClass())) {
return ((PerformanceProfiler)getSession().getProfiler()).shouldLogProfile();
}
return false;
}
/**
* Method used to set if statements should be cached. Please note that Statements can not be cached when
* using an external connection pool
*/
public void setShouldCacheAllStatements(boolean shouldCacheAllStatements) {
if (!(getSession().getDatasourceLogin() instanceof DatabaseLogin)) {
return;
}
((DatabaseLogin)getSession().getDatasourceLogin()).setShouldCacheAllStatements(shouldCacheAllStatements);
}
/**
* Used to set the statement cache size. This is only valid if using cached Statements
*/
public void setStatementCacheSize(int size) {
if (!(getSession().getDatasourceLogin() instanceof DatabaseLogin)) {
return;
}
((DatabaseLogin)getSession().getDatasourceLogin()).setStatementCacheSize(size);
}
/**
* Returns the statement cache size. Only valid if statements are being cached
*/
public int getStatementCacheSize() {
if (!(getSession().getDatasourceLogin() instanceof DatabaseLogin)) {
return 0;
}
return ((DatabaseLogin)getSession().getDatasourceLogin()).getStatementCacheSize();
}
/**
* This method provide access for setting the sequence pre-allocation size
*/
public void setSequencePreallocationSize(int size) {
if (!(getSession().getDatasourceLogin() instanceof DatabaseLogin)) {
return;
}
((DatasourcePlatform)getSession().getDatasourcePlatform()).setSequencePreallocationSize(size);
}
/**
* Method returns the value of the Sequence Preallocation size
*/
public int getSequencePreallocationSize() {
if (!(getSession().getDatasourceLogin() instanceof DatabaseLogin)) {
return 0;
}
return ((DatasourcePlatform)getSession().getDatasourcePlatform()).getSequencePreallocationSize();
}
/**
* This method allows the client to set the pool size for a particular pool, based on the pool name
* @param poolName the name of the pool to be updated.
* @param maxSize the new maximum number of connections
* @param minSize the new minimum number of connections
*/
public void updatePoolSize(String poolName, int maxSize, int minSize) {
if (ClassConstants.ServerSession_Class.isAssignableFrom(getSession().getClass())) {
ConnectionPool connectionPool = ((ServerSession)getSession()).getConnectionPool(poolName);
if (connectionPool != null) {
connectionPool.setMaxNumberOfConnections(maxSize);
connectionPool.setMinNumberOfConnections(minSize);
}
}
}
/**
* This method will return the available Connection pools within this Server Session
* @return java.util.List the available pools.
*/
public List getAvailableConnectionPools() {
Vector list = null;
if (ClassConstants.ServerSession_Class.isAssignableFrom(getSession().getClass())) {
Map pools = ((ServerSession)getSession()).getConnectionPools();
list = new Vector(pools.size());
Iterator poolNames = pools.keySet().iterator();
while (poolNames.hasNext()) {
list.add(poolNames.next());
}
} else {
list = new Vector();
}
return list;
}
/**
* This method will retrieve the size of a particular connection pool
* @param poolName the name of the pool to get the size for
* @return java.util.List a list containing two values. The first value is the Maximun size of the pool.
* The second value is the Minimum size of the pool.
*/
public List getSizeForPool(String poolName) {
Vector results = new Vector(2);
if (ClassConstants.ServerSession_Class.isAssignableFrom(getSession().getClass())) {
ConnectionPool connectionPool = ((ServerSession)getSession()).getConnectionPool(poolName);
if (connectionPool != null) {
results.add(connectionPool.getMaxNumberOfConnections());
results.add(connectionPool.getMinNumberOfConnections());
}
}
return results;
}
/**
* This method provides client with access to add a new connection pool to a EclipseLink
* ServerSession.
* @param poolName the name of the new pool
* @param maxSize the maximum number of connections in the pool
* @param minSize the minimum number of connections in the pool
* @param platform the fully qualified name of the EclipseLink platform to use with this pool.
* @param driverClassName the fully qualified name of the JDBC driver class
* @param url the URL of the database to connect to
* @param userName the user name to connect to the database with
* @param password the password to connect to the database with
* @exception ClassNotFoundException if any of the class names are misspelled.
*/
public void addNewConnectionPool(String poolName, int maxSize, int minSize, String platform, String driverClassName, String url, String userName, String password) throws ClassNotFoundException {
if (ClassConstants.ServerSession_Class.isAssignableFrom(getSession().getClass())) {
DatabaseLogin login = new DatabaseLogin();
login.setPlatformClassName(platform);
login.setDriverClassName(driverClassName);
login.setConnectionString(url);
login.setUserName(userName);
login.setEncryptedPassword(password);
((ServerSession)getSession()).addConnectionPool(poolName, login, minSize, maxSize);
}
}
/**
* This method is used to reset connections from the session to the database. Please
* Note that this will not work with a SessionBroker at this time
*/
public void resetAllConnections() {
if (ClassConstants.ServerSession_Class.isAssignableFrom(getSession().getClass())) {
Iterator enumtr = ((ServerSession)getSession()).getConnectionPools().values().iterator();
while (enumtr.hasNext()) {
ConnectionPool pool = (ConnectionPool)enumtr.next();
pool.shutDown();
pool.startUp();
}
} else if (ClassConstants.PublicInterfaceDatabaseSession_Class.isAssignableFrom(getSession().getClass())) {
getSession().getAccessor().reestablishConnection(getSession());
}
}
/**
* This method is used to return those Class Names that have identity Maps in the Session.
* Please note that SubClasses and aggregates will be missing form this list as they do not have
* separate identity maps.
* @return java.util.List contains all of the classes which have identity maps in the current session.
*/
public List getClassesInSession() {
return getSession().getIdentityMapAccessorInstance().getIdentityMapManager().getClassesRegistered();
}
/**
* This method will return a collection of the objects in the Identity Map.
* There is no particular order to these objects.
* @param className the fully qualified classname of the class to the instances of
* @exception ClassNotFoundException thrown then the IdentityMap for that class name could not be found
*/
public List getObjectsInIdentityMap(String className) throws ClassNotFoundException {
Class classToChange = (Class)getSession().getDatasourcePlatform().getConversionManager().convertObject(className, ClassConstants.CLASS);
IdentityMap map = getSession().getIdentityMapAccessorInstance().getIdentityMap(classToChange);
Vector results = new Vector(map.getSize());
Enumeration objects = map.keys();
while (objects.hasMoreElements()) {
results.add(((CacheKey)objects.nextElement()).getObject());
}
return results;
}
/**
* This method is used to return the number of objects in a particular Identity Map
* @param className the fully qualified name of the class to get number of instances of.
* @exception ClassNotFoundException thrown then the IdentityMap for that class name could not be found
*/
public Integer getNumberOfObjectsInIdentityMap(String className) throws ClassNotFoundException {
Class classToChange = (Class)getSession().getDatasourcePlatform().getConversionManager().convertObject(className, ClassConstants.CLASS);
return getSession().getIdentityMapAccessorInstance().getIdentityMap(classToChange).getSize();
}
/**
* This method is used to return a Map of the objects in a particular Identity Map's
* subcache. Only works for those identity Maps with a sub cache (ie Hard Cache Weak Identity Map)
* This method replaces getObjectsInIdentityMapSubCache(className) which returns a list instead
* of a Map
* @param className the fully qualified name of the class to get number of instances of.
* @exception ClassNotFoundException thrown then the IdentityMap for that class name could not be found
*/
public List getObjectsInIdentityMapSubCacheAsMap(String className) throws ClassNotFoundException {
Class classToChange = (Class)getSession().getDatasourcePlatform().getConversionManager().convertObject(className, ClassConstants.CLASS);
IdentityMap map = getSession().getIdentityMapAccessorInstance().getIdentityMap(classToChange);
//CR3855
List subCache = new ArrayList(0);
if (ClassConstants.HardCacheWeakIdentityMap_Class.isAssignableFrom(map.getClass())) {
subCache = ((HardCacheWeakIdentityMap)map).getReferenceCache();
}
return subCache;
}
/**
* This method is used to return the number of objects in a particular Identity Map's
* subcache. Only works for those identity Maps with a sub cache (ie Hard Cache Weak Identity Map)
* @param className the fully qualified name of the class to get number of instances of.
* @exception ClassNotFoundException thrown then the IdentityMap for that class name could not be found
*/
public Integer getNumberOfObjectsInIdentityMapSubCache(String className) throws ClassNotFoundException {
//This needs to use the Session's active class loader (not implemented yet)
Integer result = 0;
Class classToChange = (Class)getSession().getDatasourcePlatform().getConversionManager().convertObject(className, ClassConstants.CLASS);
IdentityMap map = getSession().getIdentityMapAccessorInstance().getIdentityMap(classToChange);
if (map.getClass().isAssignableFrom(ClassConstants.HardCacheWeakIdentityMap_Class)) {
List subCache = ((HardCacheWeakIdentityMap)map).getReferenceCache();
result = subCache.size();
}
return result;
}
/**
* <p>
* Return the log level
* </p>
* @param category the string representation of an EclipseLink category, e.g. "sql", "transaction" ...
* @return the log level
*/
public int getLogLevel(String category) {
return getSession().getLogLevel(category);
}
/**
* <p>
* Set the log level
* </p>
*
* @param level the new log level
*/
public void setLogLevel(int level) {
getSession().setLogLevel(level);
}
/**
* <p>
* Check if a message of the given level would actually be logged.
* </p>
*
* @param Level the log request level
* @param category the string representation of an EclipseLink category
* @return true if the given message level will be logged
*/
public boolean shouldLog(int Level, String category) {
return getSession().shouldLog(Level, category);
}
/**
* Return the DMS sensor weight
*/
public int getProfileWeight() {
if (getSession().isInProfile()) {
return getSession().getProfiler().getProfileWeight();
} else {
return 0;
}
}
/**
* This method is used to change DMS sensor weight.
*/
public void setProfileWeight(int weight) {
if (getSession().isInProfile()) {
getSession().getProfiler().setProfileWeight(weight);
}
}
/**
* This method is used to initialize the identity maps specified by className.
* @param className the fully qualified classnames identifying the identity map to initialize
*/
public synchronized void initializeIdentityMap(String className) throws ClassNotFoundException {
Class registeredClass;
//get identity map, and initialize
registeredClass = (Class)getSession().getDatasourcePlatform().getConversionManager()
.convertObject(className, ClassConstants.CLASS);
getSession().getIdentityMapAccessor().initializeIdentityMap(registeredClass);
((AbstractSession)session).log(SessionLog.INFO, SessionLog.SERVER, "jmx_mbean_runtime_services_identity_map_initialized", className);
}
/**
* This method will log the instance level locks in all Identity Maps in the session.
*/
public void printIdentityMapLocks() {
getSession().getIdentityMapAccessorInstance().getIdentityMapManager().printLocks();
}
/**
* This method will log the instance level locks in the Identity Map for the given class in the session.
*/
public void printIdentityMapLocks(String registeredClassName) {
Class registeredClass = (Class)getSession().getDatasourcePlatform().getConversionManager()
.convertObject(registeredClassName, ClassConstants.CLASS);
getSession().getIdentityMapAccessorInstance().getIdentityMapManager().printLocks(registeredClass);
}
/**
* This method assumes EclipseLink Profiling (as opposed to Java profiling).
* This will log at the INFO level a summary of all elements in the profile.
*/
public void printProfileSummary() {
if (!this.getUsesEclipseLinkProfiling()) {
return;
}
PerformanceProfiler performanceProfiler = (PerformanceProfiler)getSession().getProfiler();
getSession().getSessionLog().info(performanceProfiler.buildProfileSummary().toString());
}
/**
* INTERNAL:
* utility method to get rid of leading and trailing {}'s
*/
private String trimProfileString(String originalProfileString) {
String trimmedString;
if (originalProfileString.length() > 1) {
trimmedString = originalProfileString.substring(0, originalProfileString.length());
if ((trimmedString.charAt(0) == '{') && (trimmedString.charAt(trimmedString.length() - 1) == '}')) {
trimmedString = trimmedString.substring(1, trimmedString.length() - 1);
}
return trimmedString;
} else {
return originalProfileString;
}
}
/**
* This method assumes EclipseLink Profiling (as opposed to Java profiling).
* This will log at the INFO level a summary of all elements in the profile, categorized
* by Class.
*/
public void printProfileSummaryByClass() {
if (!this.getUsesEclipseLinkProfiling()) {
return;
}
PerformanceProfiler performanceProfiler = (PerformanceProfiler)getSession().getProfiler();
//trim the { and } from the beginning at end, because they cause problems for the logger
getSession().getSessionLog().info(trimProfileString(performanceProfiler.buildProfileSummaryByClass().toString()));
}
/**
* This method assumes EclipseLink Profiling (as opposed to Java profiling).
* This will log at the INFO level a summary of all elements in the profile, categorized
* by Query.
*/
public void printProfileSummaryByQuery() {
if (!this.getUsesEclipseLinkProfiling()) {
return;
}
PerformanceProfiler performanceProfiler = (PerformanceProfiler)getSession().getProfiler();
getSession().getSessionLog().info(trimProfileString(performanceProfiler.buildProfileSummaryByQuery().toString()));
}
/**
* This method is used to get the type of profiling.
* Possible values are: "EclipseLink" or "None".
*/
public synchronized String getProfilingType() {
if (getUsesEclipseLinkProfiling()) {
return EclipseLink_Product_Name;
} else {
return "None";
}
}
/**
* This method is used to select the type of profiling.
* Valid values are: "EclipseLink" or "None". These values are not case sensitive.
* null is considered to be "None".
*/
public synchronized void setProfilingType(String profileType) {
if ((profileType == null) || (profileType.compareToIgnoreCase("None") == 0)) {
this.setUseNoProfiling();
} else if (profileType.compareToIgnoreCase(EclipseLink_Product_Name) == 0) {
this.setUseEclipseLinkProfiling();
}
}
/**
* This method is used to turn on EclipseLink Performance Profiling
*/
public void setUseEclipseLinkProfiling() {
if (getUsesEclipseLinkProfiling()) {
return;
}
getSession().setProfiler(new PerformanceProfiler());
}
/**
* This method is used to turn off all Performance Profiling, DMS or EclipseLink.
*/
public void setUseNoProfiling() {
getSession().setProfiler(null);
}
/**
* This method answers true if EclipseLink Performance Profiling is on.
*/
public Boolean getUsesEclipseLinkProfiling() {
return getSession().getProfiler() instanceof PerformanceProfiler;
}
/**
* PUBLIC: Answer the EclipseLink log level at deployment time. This is read-only.
*/
public String getDeployedEclipseLinkLogLevel() {
return getNameForLogLevel(getDeployedSessionLog().getLevel());
}
/**
* PUBLIC: Answer the EclipseLink log level that is changeable.
* This does not affect the log level in the project (i.e. The next
* time the application is deployed, changes are forgotten)
*/
public String getCurrentEclipseLinkLogLevel() {
return getNameForLogLevel(this.getSession().getSessionLog().getLevel());
}
/**
* PUBLIC: Set the EclipseLink log level to be used at runtime.
*
* This does not affect the log level in the project (i.e. The next
* time the application is deployed, changes are forgotten)
*
* @param newLevel new log level
*/
public synchronized void setCurrentEclipseLinkLogLevel(String newLevel) {
this.getSession().setLogLevel(this.getLogLevelForName(newLevel));
}
/**
* INTERNAL: Answer the name for the log level given.
*
* @return String (one of OFF, SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST, ALL)
*/
private String getNameForLogLevel(int logLevel) {
switch (logLevel) {
case SessionLog.ALL:
return SessionLog.ALL_LABEL;
case SessionLog.SEVERE:
return SessionLog.SEVERE_LABEL;
case SessionLog.WARNING:
return SessionLog.WARNING_LABEL;
case SessionLog.INFO:
return SessionLog.INFO_LABEL;
case SessionLog.CONFIG:
return SessionLog.CONFIG_LABEL;
case SessionLog.FINE:
return SessionLog.FINE_LABEL;
case SessionLog.FINER:
return SessionLog.FINER_LABEL;
case SessionLog.FINEST:
return SessionLog.FINEST_LABEL;
case SessionLog.OFF:
return SessionLog.OFF_LABEL;
default:
return "N/A";
}
}
/**
* INTERNAL: Answer the log level for the given name.
*
* @return int for OFF, SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST, ALL
*/
private int getLogLevelForName(String levelName) {
if (levelName.equals(SessionLog.ALL_LABEL)) {
return SessionLog.ALL;
}
if (levelName.equals(SessionLog.SEVERE_LABEL)) {
return SessionLog.SEVERE;
}
if (levelName.equals(SessionLog.WARNING_LABEL)) {
return SessionLog.WARNING;
}
if (levelName.equals(SessionLog.INFO_LABEL)) {
return SessionLog.INFO;
}
if (levelName.equals(SessionLog.CONFIG_LABEL)) {
return SessionLog.CONFIG;
}
if (levelName.equals(SessionLog.FINE_LABEL)) {
return SessionLog.FINE;
}
if (levelName.equals(SessionLog.FINER_LABEL)) {
return SessionLog.FINER;
}
if (levelName.equals(SessionLog.FINEST_LABEL)) {
return SessionLog.FINEST;
}
return SessionLog.OFF;
}
/**
* INTERNAL:
* Define the deployment time data associated with logging and profiling
*
*/
protected void updateDeploymentTimeData() {
this.deployedSessionLog = (SessionLog) session.getSessionLog().clone();
if (session.getProfiler() == null) {
this.deployedSessionProfileWeight = -1;//there is no profiler
} else {
this.deployedSessionProfileWeight = session.getProfiler().getProfileWeight();
}
}
public int getDeployedSessionProfileWeight() {
return deployedSessionProfileWeight;
}
public SessionLog getDeployedSessionLog() {
return deployedSessionLog;
}
public String getObjectName() {
return objectName;
}
/**
* Return whether this session is an EclipseLink JPA session.
* The absence of this function or a value of false will signify that the session
* belongs to a provider other than EclipseLink.
*/
public boolean isJPASession() {
return true;
}
/**
* Answer the type of the EclipseLink session this MBean represents.
* Types include: "ServerSession", "DatabaseSession", "SessionBroker"
*/
public String getSessionType() {
return Helper.getShortClassName(getSession().getClass());
}
/**
* Provide an instance of 2 Dimensional Array simulating tabular format information about all
* classes in the session whose class names match the provided filter.
*
* The 2 Dimensional array contains each item with values being row object array. Each row object array
* represents EclipseLink class details info with respect to below attributes:
* ["Class Name", "Parent Class Name", "Cache Type", "Configured Size", "Current Size"]
*
*/
public Object[][] getClassSummaryDetailsUsingFilter(String filter){
try{
return tabularDataTo2DArray(buildClassSummaryDetailsUsingFilter(filter),new String[] {
"Class Name", "Parent Class Name", "Cache Type", "Configured Size", "Current Size" });
} catch (Exception exception) {
AbstractSessionLog.getLog().log(SessionLog.SEVERE, "jmx_enabled_platform_mbean_runtime_exception", PLATFORM_NAME, exception);
}
return null;
}
/**
* PUBLIC: Provide an instance of 2 Dimensional Array simulating tabular format information about all
* classes in the session.
*
* The 2 Dimensional array contains each item with values being row object array. Each row object array
* represents EclipseLink class details info with respect to below attributes:
* ["Class Name", "Parent Class Name", "Cache Type", "Configured Size", "Current Size"]
*
*/
public Object[][] getClassSummaryDetails() {
try{
return tabularDataTo2DArray(buildClassSummaryDetails(),new String[] {
"Class Name", "Parent Class Name", "Cache Type", "Configured Size", "Current Size" });
} catch (Exception exception){
AbstractSessionLog.getLog().log(SessionLog.SEVERE, "jmx_enabled_platform_mbean_runtime_exception", PLATFORM_NAME, exception);
}
return null;
}
/**
* INTERNAL:
* Answer the fully qualified names of the classes mapped in the session.
* This uses the mappedClass from the CMPPolicy.
*
* @return java.util.Vector
*/
private Vector getMappedClassNames() {
Map alreadyAdded = new HashMap();
Vector mappedClassNames = new Vector();
String mappedClassName = null;
Iterator descriptorsIterator = getSession().getProject().getDescriptors()
.values().iterator();
while (descriptorsIterator.hasNext()) {
ClassDescriptor nextDescriptor = (ClassDescriptor) descriptorsIterator.next();
// differentiate between a generated class and not, by comparing the descriptor's Java class
if (nextDescriptor.getCMPPolicy() != null) {
if (nextDescriptor.getCMPPolicy().getMappedClass() != null) {
mappedClassName = nextDescriptor.getCMPPolicy().getMappedClass().getName();
}
}
if (mappedClassName == null) {
mappedClassName = nextDescriptor.getJavaClassName();
}
if (alreadyAdded.get(mappedClassName) == null) {
alreadyAdded.put(mappedClassName, Boolean.TRUE);
mappedClassNames.addElement(mappedClassName);
}
mappedClassName = null;
}
return mappedClassNames;
}
/**
* INTERNAL:
* This method traverses the EclipseLink descriptors and returns a Vector of the descriptor's
* reference class names that match the provided filter. The filter is a comma separated
* list of strings to match against.
*
* @param filter A comma separated list of strings to match against.
* @return A Vector of class names that match the filter.
*/
public Vector getMappedClassNamesUsingFilter(String filter) {
//Output Vector
Vector outputVector = new Vector();
//Input mapped class names
Vector mappedClassNames = getMappedClassNames();
//Input filter values
ArrayList filters = new ArrayList();
StringTokenizer lineTokens = new StringTokenizer(filter, ",");
while (lineTokens.hasMoreTokens()) {
filters.add(lineTokens.nextToken());
}
for (int i = 0; i < mappedClassNames.size(); i++) {
String className = (String)mappedClassNames.get(i);
String classNameLowerCase = ((String)mappedClassNames.get(i)).toLowerCase();
for (int j = 0; j < filters.size(); j++) {
String filterValue = (Helper.rightTrimString((String)filters.get(j)).trim()).toLowerCase();
if (filterValue.indexOf('*') == 0) {
filterValue = filterValue.substring(1);
}
try {
//Note: String.matches(String regex) since jdk1.4
if (classNameLowerCase.matches(new StringBuilder().append("^.*").append(filterValue).append(".*$").toString())) {
if (!outputVector.contains(className)) {
outputVector.add(className);
}
}
} catch (PatternSyntaxException exception) {
//regular expression syntax error
AbstractSessionLog.getLog().log(SessionLog.FINEST, "pattern_syntax_error", exception);
}
}
}
Collections.sort(outputVector);
return outputVector;
}
/**
* INTERNAL:
* getCacheTypeFor: Give a more UI-friendly version of the cache type
*/
protected String getCacheTypeFor(Class identityMapClass) {
if (identityMapClass == CacheIdentityMap.class) {
return "Cache";
} else if (identityMapClass == FullIdentityMap.class) {
return "Full";
} else if (identityMapClass == HardCacheWeakIdentityMap.class) {
return "HardWeak";
} else if (identityMapClass == NoIdentityMap.class) {
return "None";
} else if (identityMapClass == SoftCacheWeakIdentityMap.class) {
return "SoftWeak";
} else if (identityMapClass == WeakIdentityMap.class) {
return "Weak";
} else if (identityMapClass == SoftIdentityMap.class) {
return "Soft";
}
return "N/A";
}
/**
* getModuleName(): Answer the name of the context-root of the application that this session is associated with.
* Answer "unknown" if there is no module name available.
* Default behavior is to return "unknown" - we override this behavior here for WebLogic.
*/
public String getModuleName() {
return getSession()
.getServerPlatform().getModuleName();
}
/**
* getApplicationName(): Answer the name of the module (EAR name) that this session is associated with.
* Answer "unknown" if there is no application name available.
* Default behavior is to return "unknown" - we override this behavior here for all platform implementors of JMXEnabledPlatform
*/
public String getApplicationName() {
return ((JMXEnabledPlatform) getSession()
.getServerPlatform()).getApplicationName();
}
/**
* Method returns if all Parameters should be bound or not
*/
public Boolean getShouldBindAllParameters() {
if (!(getSession().getDatasourceLogin() instanceof DatabaseLogin)) {
return Boolean.FALSE;
}
return ((DatabaseLogin) getSession().getDatasourceLogin()).shouldBindAllParameters();
}
/**
* Return the size of strings after which will be bound into the statement
* If we are not using a DatabaseLogin, or we're not using string binding,
* answer 0 (zero).
*/
public Integer getStringBindingSize() {
if (!(getSession().getDatasourceLogin() instanceof DatabaseLogin)) {
return 0;
}
if (!getSession().getDatasourceLogin().getPlatform().usesStringBinding()) {
return 0;
}
return ((DatabaseLogin) getSession().getDatasourceLogin()).getStringBindingSize();
}
/**
* This method will return if batchWriting is in use or not.
*/
public Boolean getUsesBatchWriting() {
return getSession().getDatasourceLogin().getPlatform().usesBatchWriting();
}
/**
* This method will return a long indicating the exact time in Milliseconds that the
* session connected to the database.
*/
public Long getTimeConnectionEstablished() {
return ((DatabaseSessionImpl) getSession()).getConnectedTime();
}
/**
* This method will return if batchWriting is in use or not.
*/
public Boolean getUsesJDBCBatchWriting() {
if (!(getSession().getDatasourceLogin().getDatasourcePlatform() instanceof DatabasePlatform)) {
return Boolean.FALSE;
}
return getSession().getDatasourceLogin().getPlatform().usesJDBCBatchWriting();
}
/**
* Shows if Byte Array Binding is turned on or not
*/
public Boolean getUsesByteArrayBinding() {
if (!(getSession().getDatasourceLogin().getDatasourcePlatform() instanceof DatabasePlatform)) {
return Boolean.FALSE;
}
return getSession().getDatasourceLogin().getPlatform().usesByteArrayBinding();
}
/**
* Shows if native SQL is being used
*/
public Boolean getUsesNativeSQL() {
if (!(getSession().getDatasourceLogin().getDatasourcePlatform() instanceof DatabasePlatform)) {
return Boolean.FALSE;
}
return getSession().getDatasourceLogin().getPlatform().usesNativeSQL();
}
/**
* This method indicates if streams are being used for binding
*/
public Boolean getUsesStreamsForBinding() {
if (!(getSession().getDatasourceLogin().getDatasourcePlatform() instanceof DatabasePlatform)) {
return Boolean.FALSE;
}
return getSession().getDatasourceLogin().getPlatform().usesStreamsForBinding();
}
/**
* This method indicates if Strings are being bound
*/
public Boolean getUsesStringBinding() {
if (!(getSession().getDatasourceLogin() instanceof DatabaseLogin)) {
return Boolean.FALSE;
}
return getSession().getDatasourceLogin().getPlatform().usesStringBinding();
}
/**
* Returns if statements should be cached or not
*/
public boolean getShouldCacheAllStatements() {
if (!(getSession().getDatasourceLogin() instanceof DatabaseLogin)) {
return Boolean.FALSE;
}
return ((DatabaseLogin) getSession().getDatasourceLogin()).shouldCacheAllStatements();
}
/**
* Used to clear the statement cache. Only valid if statements are being cached
*/
public synchronized void clearStatementCache() {
if (!(getSession().getDatasourceLogin() instanceof DatabaseLogin)) {
return;
}
((DatabaseAccessor)getSession().getAccessor()).clearStatementCache(getSession());
((AbstractSession)session).log(SessionLog.INFO, SessionLog.SERVER, "jmx_mbean_runtime_services_statement_cache_cleared");
}
/**
* This method will print the available Connection pools to the SessionLog.
*/
public void printAvailableConnectionPools() {
if (ClassConstants.ServerSession_Class.isAssignableFrom(getSession().getClass())) {
Map pools = ((ServerSession)getSession()).getConnectionPools();
Iterator poolNames = pools.keySet().iterator();
while (poolNames.hasNext()) {
String poolName = poolNames.next().toString();
((AbstractSession)session).log(SessionLog.INFO, SessionLog.SERVER, "jmx_mbean_runtime_services_pool_name", poolName);
}
} else {
((AbstractSession)session).log(SessionLog.INFO, SessionLog.SERVER, "jmx_mbean_runtime_services_no_connection_pools_available");
}
}
/**
* This method will retrieve the max size of a particular connection pool
* @param poolName the name of the pool to get the max size for
* @return Integer for the max size of the pool. Return -1 if pool doesn't exist.
*/
public Integer getMaxSizeForPool(String poolName) {
if (ClassConstants.ServerSession_Class.isAssignableFrom(getSession().getClass())) {
ConnectionPool connectionPool = ((ServerSession)getSession()).getConnectionPool(poolName);
if (connectionPool != null) {
return connectionPool.getMaxNumberOfConnections();
}
}
return -1;
}
/**
* This method will retrieve the min size of a particular connection pool
* @param poolName the name of the pool to get the min size for
* @return Integer for the min size of the pool. Return -1 if pool doesn't exist.
*/
public Integer getMinSizeForPool(String poolName) {
if (ClassConstants.ServerSession_Class.isAssignableFrom(getSession().getClass())) {
ConnectionPool connectionPool = ((ServerSession)getSession()).getConnectionPool(poolName);
if (connectionPool != null) {
return connectionPool.getMinNumberOfConnections();
}
}
return -1;
}
/**
* This method is used to output those Class Names that have identity Maps in the Session.
* Please note that SubClasses and aggregates will be missing from this list as they do not have
* separate identity maps.
*/
public void printClassesInSession() {
Vector classes = getSession().getIdentityMapAccessorInstance().getIdentityMapManager().getClassesRegistered();
int index;
if (classes.isEmpty()) {
((AbstractSession)session).log(SessionLog.INFO, SessionLog.SERVER, "jmx_mbean_runtime_services_no_classes_in_session");
return;
}
for (index = 0; index < classes.size(); index++) {
getSession().getSessionLog().log(SessionLog.FINEST, (String)classes.elementAt(index));
}
}
/**
* This method will log the objects in the Identity Map.
* There is no particular order to these objects.
* @param className the fully qualified classname identifying the identity map
* @exception ClassNotFoundException thrown then the IdentityMap for that class name could not be found
*/
public void printObjectsInIdentityMap(String className) throws ClassNotFoundException {
Class classWithMap = (Class)getSession().getDatasourcePlatform().getConversionManager().convertObject(className, ClassConstants.CLASS);
IdentityMap map = getSession().getIdentityMapAccessorInstance().getIdentityMap(classWithMap);
//check if the identity map exists
if (null == map) {
((AbstractSession)session).log(SessionLog.INFO, SessionLog.SERVER, "jmx_mbean_runtime_services_identity_map_non_existent", className);
return;
}
//check if there are any objects in the identity map. Print if so.
Enumeration objects = map.keys();
if (!objects.hasMoreElements()) {
((AbstractSession)session).log(SessionLog.INFO, SessionLog.SERVER, "jmx_mbean_runtime_services_identity_map_empty", className);
}
CacheKey cacheKey;
while (objects.hasMoreElements()) {
cacheKey = (CacheKey)objects.nextElement();
if(null != cacheKey && null != cacheKey.getKey() && null != cacheKey.getObject()) {
((AbstractSession)session).log(SessionLog.INFO, SessionLog.SERVER, "jmx_mbean_runtime_services_print_cache_key_value",
cacheKey.getKey().toString(), cacheKey.getObject().toString());
}
}
}
/**
* This method will log the types of Identity Maps in the session.
*/
public void printAllIdentityMapTypes() {
Vector classesRegistered = getSession().getIdentityMapAccessorInstance().getIdentityMapManager().getClassesRegistered();
String registeredClassName;
Class registeredClass;
//Check if there aren't any classes registered
if (classesRegistered.size() == 0) {
((AbstractSession)session).log(SessionLog.INFO, SessionLog.SERVER, "jmx_mbean_runtime_services_no_identity_maps_in_session");
return;
}
//get each identity map, and log the type
for (int index = 0; index < classesRegistered.size(); index++) {
registeredClassName = (String)classesRegistered.elementAt(index);
registeredClass = (Class)getSession().getDatasourcePlatform().getConversionManager().convertObject(registeredClassName, ClassConstants.CLASS);
IdentityMap map = getSession().getIdentityMapAccessorInstance().getIdentityMap(registeredClass);
((AbstractSession)session).log(SessionLog.INFO, SessionLog.SERVER, "jmx_mbean_runtime_services_identity_map_class",
registeredClassName, map.getClass());
}
}
/**
* This method will log all objects in all Identity Maps in the session.
*/
public void printObjectsInIdentityMaps() {
Vector classesRegistered = getSession().getIdentityMapAccessorInstance().getIdentityMapManager().getClassesRegistered();
String registeredClassName;
//Check if there aren't any classes registered
if (classesRegistered.size() == 0) {
((AbstractSession)session).log(SessionLog.INFO, SessionLog.SERVER, "jmx_mbean_runtime_services_no_identity_maps_in_session");
return;
}
//get each identity map, and log the type
for (int index = 0; index < classesRegistered.size(); index++) {
registeredClassName = (String)classesRegistered.elementAt(index);
try {
this.printObjectsInIdentityMap(registeredClassName);
} catch (ClassNotFoundException classNotFound) {
//we are enumerating registered classes, so this shouldn't happen. Print anyway
classNotFound.printStackTrace();
AbstractSessionLog.getLog().log(SessionLog.SEVERE, "jmx_enabled_platform_mbean_runtime_exception", PLATFORM_NAME, classNotFound);
}
}
}
/**
* This method will SUM and return the number of objects in all Identity Maps in the session.
*/
public Integer getNumberOfObjectsInAllIdentityMaps() {
Vector classesRegistered = getSession().getIdentityMapAccessorInstance().getIdentityMapManager().getClassesRegistered();
String registeredClassName;
int sum = 0;
//Check if there aren't any classes registered
if (classesRegistered.size() == 0) {
((AbstractSession)session).log(SessionLog.INFO, SessionLog.SERVER, "jmx_mbean_runtime_services_no_identity_maps_in_session");
return 0;
}
//get each identity map, and log the size
for (int index = 0; index < classesRegistered.size(); index++) {
registeredClassName = (String)classesRegistered.elementAt(index);
try {
sum += this.getNumberOfObjectsInIdentityMap(registeredClassName);
} catch (ClassNotFoundException classNotFound) {
//we are enumerating registered classes, so this shouldn't happen. Print anyway
classNotFound.printStackTrace();
AbstractSessionLog.getLog().log(SessionLog.SEVERE, "jmx_enabled_platform_mbean_runtime_exception", PLATFORM_NAME, classNotFound);
}
}
return sum;
}
/**
* This method will answer the number of persistent classes contained in the session.
* This does not include aggregates.
*/
public Integer getNumberOfPersistentClasses() {
Map classesTable = new HashMap();
ClassDescriptor currentDescriptor;
//use a table to eliminate duplicate classes. Ignore Aggregates
Iterator descriptors = getSession().getProject().getDescriptors().values().iterator();
while (descriptors.hasNext()) {
currentDescriptor = (ClassDescriptor)descriptors.next();
if (!currentDescriptor.isAggregateDescriptor()) {
classesTable.put(currentDescriptor.getJavaClassName(), Boolean.TRUE);
}
}
return classesTable.size();
}
/**
* Return the log type, either "EclipseLink", "Java" or the simple name of the logging class used.
*
* @return the log type
*/
public String getLogType() {
if (this.getSession().getSessionLog().getClass() == JavaLog.class) {
return "Java";
} else if (this.getSession().getSessionLog().getClass() == DefaultSessionLog.class) {
return EclipseLink_Product_Name;
} else {
return this.getSession().getSessionLog().getClass().getSimpleName();
}
}
/**
* Return the database platform used by the DatabaseSession.
*
* @return String databasePlatform
*/
public String getDatabasePlatform() {
return getSession().getDatasourcePlatform().getClass().getName();
}
/**
* Return JDBCConnection detail information. This includes URL and datasource information.
*/
public synchronized String getJdbcConnectionDetails() {
return getSession().getLogin().getConnector().getConnectionDetails();
}
/**
* Return connection pool type. Values include: "Internal", "External" and "N/A".
*/
public synchronized String getConnectionPoolType() {
if (getSession().getLogin().shouldUseExternalConnectionPooling()) {
return "External";
} else {
return "N/A";
}
}
/**
* Return db driver class name. This only applies to DefaultConnector. Return "N/A" otherwise.
*/
public synchronized String getDriver() {
if (getSession().getLogin().getConnector() instanceof DefaultConnector) {
return getSession().getLogin().getDriverClassName();
}
return "N/A";
}
/**
* Return the log filename. This returns the fully qualified path of the log file when
* EclipseLink DefaultSessionLog instance is used. Null is returned otherwise.
*
* @return String logFilename
*/
public String getLogFilename() {
// returns String or null.
if ( session.getSessionLog() instanceof DefaultSessionLog) {
return ((DefaultSessionLog)session.getSessionLog()).getWriterFilename();
} else {
return null;
}
}
/**
* This method is used to initialize the identity maps in the session.
*/
public synchronized void initializeAllIdentityMaps() {
getSession().getIdentityMapAccessor().initializeAllIdentityMaps();
}
/**
* This method is used to initialize the identity maps specified by the Vector of classNames.
*
* @param classNames String[] of fully qualified classnames identifying the identity maps to initialize
*/
public synchronized void initializeIdentityMaps(String[] classNames) throws ClassNotFoundException {
for (int index = 0; index < classNames.length; index++) {
initializeIdentityMap(classNames[index]);
}
}
/**
* This method is used to invalidate the identity maps in the session.
*/
public synchronized void invalidateAllIdentityMaps() {
Vector classesRegistered = getSession().getIdentityMapAccessorInstance().getIdentityMapManager().getClassesRegistered();
String registeredClassName;
Class registeredClass;
if (classesRegistered.isEmpty()) {
((AbstractSession)session).log(SessionLog.INFO, SessionLog.SERVER, "jmx_mbean_runtime_services_no_identity_maps_in_session");
}
//get each identity map, and invalidate
for (int index = 0; index < classesRegistered.size(); index++) {
registeredClassName = (String)classesRegistered.elementAt(index);
registeredClass = (Class)getSession().getDatasourcePlatform().getConversionManager()
.convertObject(registeredClassName, ClassConstants.CLASS);
getSession().getIdentityMapAccessor().invalidateClass(registeredClass);
((AbstractSession)session).log(SessionLog.INFO, SessionLog.SERVER, "jmx_mbean_runtime_services_identity_map_invalidated", registeredClassName);
}
}
/**
* This method is used to invalidate the identity maps specified by the String[] of classNames.
*
* @param classNamesParam String[] of fully qualified classnames identifying the identity maps to invalidate
* @param recurse Boolean indicating if we want to invalidate the children identity maps too
*/
public synchronized void invalidateIdentityMaps(String[] classNamesParam, Boolean recurse) throws ClassNotFoundException {
String[] classNames = classNamesParam;
for (int index = 0; index < classNames.length; index++) {
invalidateIdentityMap(classNames[index], recurse);
}
}
/**
* This method is used to invalidate the identity maps specified by className. This does not
* invalidate the children identity maps
*
* @param className the fully qualified classname identifying the identity map to invalidate
*/
public synchronized void invalidateIdentityMap(String className) throws ClassNotFoundException {
this.invalidateIdentityMap(className, Boolean.FALSE);
}
/**
* This method is used to invalidate the identity maps specified by className.
*
* @param className the fully qualified classname identifying the identity map to invalidate
* @param recurse Boolean indicating if we want to invalidate the children identity maps too
*/
public synchronized void invalidateIdentityMap(String className, Boolean recurse) throws ClassNotFoundException {
Class registeredClass;
//get identity map, and invalidate
registeredClass = (Class)getSession().getDatasourcePlatform().getConversionManager()
.convertObject(className, ClassConstants.CLASS);
getSession().getIdentityMapAccessor().invalidateClass(registeredClass);
((AbstractSession)session).log(SessionLog.INFO, SessionLog.SERVER, "jmx_mbean_runtime_services_identity_map_invalidated", className);
}
/**
*
* INTERNAL:
* Convert the TabularData to a two-dimensional array
* @param tdata the TabularData to be converted
* @param names the order of the columns
* @return a two-dimensional array
*/
private Object[][] tabularDataTo2DArray(TabularData tdata, String[] names) throws Exception {
if(tdata==null){
return null;
}
Object[] rows = tdata.values().toArray();
Object[][] data = new Object[rows.length][];
for (int i = 0; i < rows.length; i++) {
CompositeData cdata = ((CompositeData) rows[i]);
Object[] returnRow = new Object[names.length];
for (int j = 0; j < names.length; j++) {
String name = names[j];
Object value = cdata.get(name);
returnRow[j] = name + " : " + String.valueOf(value);
}
data[i] = returnRow;
}
return data;
}
/**
* INTERNAL:
* Define the session that this instance is providing runtime services for
*
* @param newSession The session to be used with these RuntimeServices
*/
protected void setSession(AbstractSession newSession) {
this.session = newSession;
this.updateDeploymentTimeData();
}
/**
* INTERNAL:
* Answer the CompositeType describing the CompositeData that we return for
* each IdentityMap (or subclass).
*
* This is mostly for the client side to see what kind of information is returned.
* @return javax.management.openmbean.CompositeType
*/
private CompositeType buildCompositeTypeForClassSummaryDetails() throws OpenDataException {
return new CompositeType("Class Details", "Details of class for Class Summary", new String[] {
"Class Name", "Parent Class Name", "Cache Type", "Configured Size", "Current Size" }, new String[] {
"Class Name", "Parent Class Name", "Cache Type", "Configured Size", "Current Size" }, new OpenType[] {
SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.STRING });
}
/**
* Provide a list of instance of ClassSummaryDetail containing information about the
* classes in the session whose class names match the provided filter.
*
* ClassSummaryDetail is a model specific class that can be used internally by the Portable JMX Framework to
* convert class attribute to JMX required open type, it has:-
* 1. model specific type that needs to be converted : ["Class Name", "Parent Class Name", "Cache Type", "Configured Size", "Current Size"]
* 2. convert methods.
*
* @param filter A comma separated list of strings to match against.
* @return A ArrayList of instance of ClassSummaryDetail containing class information for the class names that match the filter.
*/
/**
* Provide a list of instance of ClassSummaryDetail containing information about the
* classes in the session whose class names match the provided filter.
*
* ClassSummaryDetail is a model specific class that can be used internally by the Portable JMX Framework to
* convert class attribute to JMX required open type, it has:-
* 1. model specific type that needs to be converted : ["Class Name", "Parent Class Name", "Cache Type", "Configured Size", "Current Size"]
* 2. convert methods.
*
* @param filter A comma separated list of strings to match against.
* @return A ArrayList of instance of ClassSummaryDetail containing class information for the class names that match the filter.
*/
public List <ClassSummaryDetailBase> getClassSummaryDetailsUsingFilterArray(String filter) {
// if the filter is null, return all the details
if (filter == null) {
return getClassSummaryDetailsArray();
}
try {
Vector mappedClassNames = getMappedClassNamesUsingFilter(filter);
String mappedClassName;
List classSummaryDetails = new ArrayList<ClassSummaryDetailBase>();
// Check if there aren't any classes mapped
if (mappedClassNames.size() == 0) {
return null;
}
// get details for each class, and add the details to the summary
for (int index = 0; index < mappedClassNames.size(); index++) {
mappedClassName = (String)mappedClassNames.elementAt(index);
classSummaryDetails.add(buildLowlevelDetailsFor(mappedClassName));
}
return classSummaryDetails;
} catch (Exception openTypeException) {
AbstractSessionLog.getLog().log(SessionLog.SEVERE, "jmx_enabled_platform_mbean_runtime_exception", PLATFORM_NAME, openTypeException);
openTypeException.printStackTrace();
}
// wait to get requirements from EM
return null;
}
/**
* Provide a list of instance of ClassSummaryDetail containing information about all
* classes in the session.
*
* ClassSummaryDetail is a model specific class that can be used internally by the Portable JMX Framework to
* convert class attribute to JMX required open type, it has:-
* 1. model specific type that needs to be converted : ["Class Name", "Parent Class Name", "Cache Type", "Configured Size", "Current Size"]
* 2. convert methods.
*
* @return A List of instance of ClassSummaryDetail objects containing class information for the class names that match the filter.
*/
public List <ClassSummaryDetailBase> getClassSummaryDetailsArray() {
try {
Vector mappedClassNames = getMappedClassNames();
List classSummaryDetails = new ArrayList<ClassSummaryDetailBase>();
// Check if there aren't any classes mapped
if (mappedClassNames.size() == 0) {
return null;
}
// get details for each class, and add the details to the summary
for (int index = 0; index < mappedClassNames.size(); index++) {
String mappedClassName = (String)mappedClassNames.elementAt(index);
classSummaryDetails.add(buildLowlevelDetailsFor(mappedClassName));
}
return classSummaryDetails;
} catch (Exception openTypeException) {
AbstractSessionLog.getLog().log(SessionLog.SEVERE, "jmx_enabled_platform_mbean_runtime_exception", PLATFORM_NAME, openTypeException);
openTypeException.printStackTrace();
}
// wait to get requirements from EM
return null;
}
/**
* INTERNAL:
* Answer the TabularType describing the TabularData that we return from
* getCacheSummaryDetails() and getCacheSummaryDetails(String filter)
*
* This is mostly for the client side to see what kind of information is returned.
*
* @return javax.management.openmbean.TabularType
*/
private TabularType buildTabularTypeForClassSummaryDetails() throws OpenDataException {
return new TabularType(getSessionName(), "Session description", buildCompositeTypeForClassSummaryDetails(),
new String[] { "Class Name" });
}
/**
* INTERNAL:
* Answer the CompositeData containing the cache details for the given mappedClassName
* This uses a CompositeDataSupport, which implements CompositeData
*
* @param mappedClassName fullyQualified class name of the class
* @param detailsType describes the format of the returned CompositeData
* @return javax.management.openmbean.CompositeData
*/
private CompositeData buildDetailsFor(String mappedClassName, CompositeType detailsType) throws Exception {
return new CompositeDataSupport(detailsType, buildLowlevelDetailsFor(mappedClassName));
}
/**
* INTERNAL:
* Helper to build a HashMap to help in the construction of a CompositeData
*
* @param mappedClassName fullyQualified class name of the class
* @return HashMap
*/
private HashMap buildLowlevelDetailsFor(String mappedClassName) {
Class mappedClass = (Class)getSession().getDatasourcePlatform().getConversionManager().convertObject(mappedClassName, ClassConstants.CLASS);
ClassDescriptor descriptor = getSession().getProject().getDescriptor(mappedClass);
String cacheType = "";
String configuredSize = "";
String currentSize = "";
String parentClassName = "";
// Aggregate descriptors do not have an IdentityMap
if (!descriptor.isAggregateDescriptor()) {
IdentityMap identityMap = getSession().getIdentityMapAccessorInstance().getIdentityMap(descriptor);
cacheType = getCacheTypeFor(identityMap.getClass());
configuredSize = String.valueOf(identityMap.getMaxSize());
//show the current size, including subclasses
currentSize = String.valueOf(identityMap.getSize(mappedClass, true));
}
//If I have a parent class name, get it. Otherwise, leave blank
if (descriptor.hasInheritance()) {
if (descriptor.getInheritancePolicy().getParentDescriptor() != null) {
parentClassName = descriptor.getInheritancePolicy().getParentClassName();
}
}
boolean isChildDescriptor = descriptor.isChildDescriptor();
HashMap details = new HashMap(5);
details.put("Class Name", mappedClassName);
details.put("Cache Type", (isChildDescriptor ? "" : cacheType));
details.put("Configured Size", (isChildDescriptor ? "" : configuredSize));
details.put("Current Size", currentSize);
details.put("Parent Class Name", parentClassName);
return details;
}
/**
* INTERNAL:
* Provide an instance of TabularData containing information about the
* classes in the session whose class names match the provided filter.
*
* The TabularData contains rowData with values being CompositeData(s)
*
* CompositeData has:
* CompositeType: column names are ["Class Name", "Parent Class Name", "Cache Type", "Configured Size", "Current Size"]
*
* Each CompositeData can have get(myColumnName) sent to it.
*
*
* @param filter A comma separated list of strings to match against.
* @return A TabularData of information for the class names that match the filter.
*/
private TabularData buildClassSummaryDetailsUsingFilter(String filter) {
// if the filter is null, return all the details
if (filter == null) {
return buildClassSummaryDetails();
}
try {
Vector mappedClassNames = getMappedClassNamesUsingFilter(filter);
String mappedClassName;
TabularDataSupport rowData = new TabularDataSupport(buildTabularTypeForClassSummaryDetails());
// Check if there aren't any classes mapped
if (mappedClassNames.size() == 0) {
return null;
}
// get details for each class, and add the details to the summary
for (int index = 0; index < mappedClassNames.size(); index++) {
mappedClassName = (String)mappedClassNames.elementAt(index);
String[] key = new String[] { mappedClassName };
rowData.put(key, buildDetailsFor(mappedClassName, rowData.getTabularType().getRowType()));
}
return rowData;
} catch (Exception exception) {
AbstractSessionLog.getLog().log(SessionLog.SEVERE, "jmx_enabled_platform_mbean_runtime_exception", PLATFORM_NAME, exception);
}
// wait to get requirements from EM
return null;
}
/**
* INTERNAL:
* Provide an instance of TabularData containing information about all
* classes in the session.
*
* The TabularData contains rowData with values being CompositeData(s)
*
* CompositeData has:
* CompositeType: column names are ["Class Name", "Parent Class Name", "Cache Type", "Configured Size", "Current Size"]
*
* Each CompositeData can have get(myColumnName) sent to it.
*
*/
private TabularData buildClassSummaryDetails() {
try {
Vector mappedClassNames = getMappedClassNames();
String mappedClassName;
TabularDataSupport rowData = new TabularDataSupport(buildTabularTypeForClassSummaryDetails());
// Check if there aren't any classes mapped
if (mappedClassNames.size() == 0) {
return null;
}
// get details for each class, and add the details to the summary
for (int index = 0; index < mappedClassNames.size(); index++) {
mappedClassName = (String)mappedClassNames.elementAt(index);
String[] key = new String[] { mappedClassName };
rowData.put(key, buildDetailsFor(mappedClassName, rowData.getTabularType().getRowType()));
}
return rowData;
} catch (Exception exception) {
AbstractSessionLog.getLog().log(SessionLog.SEVERE, "jmx_enabled_platform_mbean_runtime_exception", PLATFORM_NAME, exception);
}
// wait to get requirements from EM
return null;
}
}