View Javadoc
1   /*
2    * Licensed under the GPL License. You may not use this file except in compliance with the License.
3    * You may obtain a copy of the License at
4    *
5    *   https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
6    *
7    * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
8    * WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
9    * PURPOSE.
10   */
11  package psiprobe.beans;
12  
13  import java.util.ArrayList;
14  import java.util.List;
15  import java.util.Set;
16  
17  import javax.management.MBeanServer;
18  import javax.management.MBeanServerFactory;
19  import javax.management.MalformedObjectNameException;
20  import javax.management.ObjectName;
21  import javax.naming.NamingException;
22  import javax.sql.DataSource;
23  
24  import org.apache.catalina.Context;
25  import org.slf4j.Logger;
26  import org.slf4j.LoggerFactory;
27  import org.w3c.dom.Element;
28  import org.w3c.dom.Node;
29  import org.w3c.dom.NodeList;
30  
31  import psiprobe.model.ApplicationResource;
32  import psiprobe.model.DataSourceInfo;
33  
34  /**
35   * An Adapter to convert information retrieved from JBoss JMX beans into internal resource model.
36   */
37  public class JBossResourceResolverBean implements ResourceResolver {
38  
39    /** The Constant logger. */
40    private static final Logger logger = LoggerFactory.getLogger(JBossResourceResolverBean.class);
41  
42    @Override
43    public MBeanServer getMBeanServer() {
44      for (MBeanServer server : MBeanServerFactory.findMBeanServer(null)) {
45        if ("jboss".equals(server.getDefaultDomain())
46            || "DefaultDomain".equals(server.getDefaultDomain())) {
47          return server;
48        }
49      }
50      return null;
51    }
52  
53    @Override
54    public boolean supportsPrivateResources() {
55      return false;
56    }
57  
58    @Override
59    public boolean supportsGlobalResources() {
60      return true;
61    }
62  
63    @Override
64    public boolean supportsDataSourceLookup() {
65      return false;
66    }
67  
68    @Override
69    public List<ApplicationResource> getApplicationResources() throws NamingException {
70  
71      List<ApplicationResource> resources = new ArrayList<>();
72  
73      MBeanServer server = getMBeanServer();
74      if (server != null) {
75        try {
76          Set<ObjectName> dsNames =
77              server.queryNames(new ObjectName("jboss.jca:service=ManagedConnectionPool,*"), null);
78          for (ObjectName objectNameManagedConnectionPool : dsNames) {
79            ApplicationResource resource = new ApplicationResource();
80            resource.setName(objectNameManagedConnectionPool.getKeyProperty("name"));
81            resource.setType("jboss");
82            String criteria =
83                (String) server.getAttribute(objectNameManagedConnectionPool, "Criteria");
84            if ("ByApplication".equals(criteria)) {
85              resource.setAuth("Application");
86            } else if ("ByContainerAndApplication".equals(criteria)) {
87              resource.setAuth("Both");
88            } else {
89              resource.setAuth("Container");
90            }
91            DataSourceInfo dsInfo = new DataSourceInfo();
92            dsInfo.setMaxConnections(
93                (Integer) server.getAttribute(objectNameManagedConnectionPool, "MaxSize"));
94            dsInfo.setEstablishedConnections(
95                (Integer) server.getAttribute(objectNameManagedConnectionPool, "ConnectionCount"));
96            dsInfo.setBusyConnections(
97                ((Long) server.getAttribute(objectNameManagedConnectionPool, "InUseConnectionCount"))
98                    .intValue());
99            ObjectName objectNameConnectionFactory = new ObjectName(
100               "jboss.jca:service=ManagedConnectionFactory,name=" + resource.getName());
101           Element elm = (Element) server.getAttribute(objectNameConnectionFactory,
102               "ManagedConnectionFactoryProperties");
103 
104           if (elm != null) {
105             NodeList nl = elm.getChildNodes();
106             for (int i = 0; i < nl.getLength(); i++) {
107               Node node = nl.item(i);
108               Node na = node.getAttributes().getNamedItem("name");
109               if (na != null) {
110                 if ("ConnectionURL".equals(na.getNodeValue())) {
111                   dsInfo.setJdbcUrl(node.getFirstChild().getNodeValue());
112                 }
113 
114                 if ("UserName".equals(na.getNodeValue())) {
115                   dsInfo.setUsername(node.getFirstChild().getNodeValue());
116                 }
117 
118                 // JMS datasource
119                 if ("JmsProviderAdapterJNDI".equals(na.getNodeValue())) {
120                   dsInfo.setJdbcUrl(node.getFirstChild().getNodeValue());
121                   resource.setType("jms");
122                 }
123               }
124             }
125           }
126 
127           dsInfo.setResettable(true);
128 
129           resource.setDataSourceInfo(dsInfo);
130           resources.add(resource);
131         }
132       } catch (Exception e) {
133         logger.error("There was an error querying JBoss JMX server:", e);
134       }
135     }
136     return resources;
137   }
138 
139   /**
140    * Gets the application resources.
141    *
142    * @param context the context
143    *
144    * @return the application resources
145    *
146    * @throws NamingException the naming exception
147    */
148   public List<ApplicationResource> getApplicationResources(Context context) throws NamingException {
149     // TODO 11/23/2023 Not implemented
150     return new ArrayList<>();
151   }
152 
153   @Override
154   public List<ApplicationResource> getApplicationResources(Context context,
155       ContainerWrapperBean containerWrapper) throws NamingException {
156     // TODO 11/23/2023 Not implemented
157     throw new UnsupportedOperationException("Not supported yet.");
158   }
159 
160   @Override
161   public boolean resetResource(Context context, String resourceName,
162       ContainerWrapperBean containerWrapper) throws NamingException {
163     try {
164       ObjectName objectNamePool =
165           new ObjectName("jboss.jca:service=ManagedConnectionPool,name=" + resourceName);
166       MBeanServer server = getMBeanServer();
167       if (server != null) {
168         try {
169           server.invoke(objectNamePool, "stop", null, null);
170           server.invoke(objectNamePool, "start", null, null);
171           return true;
172         } catch (Exception e) {
173           logger.error("Could not reset resource '{}'", resourceName, e);
174         }
175       }
176       return false;
177     } catch (MalformedObjectNameException e) {
178       logger.trace("", e);
179       throw new NamingException(
180           "Resource name: \"" + resourceName + "\" makes a malformed ObjectName");
181     }
182   }
183 
184   @Override
185   public DataSource lookupDataSource(Context context, String resourceName,
186       ContainerWrapperBean containerWrapper) throws NamingException {
187     throw new UnsupportedOperationException(
188         "This feature has not been implemented for JBoss server yet.");
189   }
190 
191 }