View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *  http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.geronimo.mavenplugins.geronimo;
21  
22  import java.util.HashMap;
23  import java.util.Map;
24  import java.util.Set;
25  import java.util.Iterator;
26  import java.io.IOException;
27  
28  import javax.management.remote.JMXServiceURL;
29  import javax.management.remote.JMXConnector;
30  import javax.management.remote.JMXConnectorFactory;
31  import javax.management.MBeanServerConnection;
32  
33  //
34  // FIXME: It should be possible to query state with-out any Geronimo classes,
35  //        just using JMX interfaces.
36  //
37  
38  import org.apache.geronimo.gbean.AbstractName;
39  import org.apache.geronimo.gbean.AbstractNameQuery;
40  import org.apache.geronimo.kernel.Kernel;
41  import org.apache.geronimo.kernel.config.PersistentConfigurationList;
42  
43  import org.apache.commons.logging.Log;
44  import org.apache.commons.logging.LogFactory;
45  
46  /**
47   * Helper to communicate with a remote server via JMX.
48   *
49   * @version $Rev: 442872 $ $Date: 2006-09-12 23:55:19 -0700 (Tue, 12 Sep 2006) $
50   */
51  public class ServerProxy
52  {
53      private static final Log log = LogFactory.getLog(ServerProxy.class);
54  
55      private JMXServiceURL url;
56  
57      private Map environment;
58  
59      private MBeanServerConnection mbeanConnection;
60  
61      private Throwable lastError;
62  
63      public ServerProxy(final JMXServiceURL url, final Map environment) throws Exception {
64          init(url, environment);
65      }
66  
67      public ServerProxy(final String hostname, final int port, final String username, final String password) throws Exception {
68          //
69          // TODO: Check if this is the right way to build up the URI
70          //
71          
72          this("service:jmx:rmi://" + hostname + "/jndi/rmi://" + hostname + ":" + port + "/JMXConnector", username, password);
73      }
74  
75      public ServerProxy(final String url, final String username, final String password) throws Exception {
76          assert url != null;
77          assert username != null;
78          assert password != null;
79          
80          Map env = new HashMap();
81          env.put("jmx.remote.credentials", new String[] {username, password});
82  
83          init(new JMXServiceURL(url), env);
84      }
85  
86      private void init(final JMXServiceURL url, final Map environment) throws Exception {
87          assert url != null;
88          assert environment != null;
89          
90          this.url = url;
91          this.environment = new HashMap();
92          this.environment.put("jmx.remote.credentials", new String[] {"system", "manager"});
93  
94          log.debug("Initialized with URL: " + url + ", environment: " + environment);
95      }
96  
97      private MBeanServerConnection getConnection() throws IOException {
98          if (this.mbeanConnection == null) {
99              log.debug("Connecting to: " + url);
100             
101             JMXConnector connector = JMXConnectorFactory.connect(url, environment);
102             this.mbeanConnection = connector.getMBeanServerConnection();
103             
104             log.debug("Connected");
105         }
106 
107         return mbeanConnection;
108     }
109 
110     public boolean isFullyStarted() {
111         boolean fullyStarted = true;
112 
113         try {
114             AbstractNameQuery query = new AbstractNameQuery(PersistentConfigurationList.class.getName());
115             Set result = listGBeans(query);
116             Iterator iter = result.iterator();
117             while (iter.hasNext()) {
118                 AbstractName name = (AbstractName)iter.next();
119                 boolean started = getBooleanAttribute(name, "kernelFullyStarted");
120                 if (!started) {
121                     fullyStarted = false;
122                     break;
123                 }
124             }
125         }
126         catch (IOException e) {
127             log.debug("Connection failure; ignoring", e);
128             fullyStarted = false;
129             lastError = e;
130         }
131         catch (Exception e) {
132             log.debug("Unable to determine if the server is fully started", e);
133             fullyStarted = false;
134             lastError = e;
135         }
136         
137         return fullyStarted;
138     }
139 
140     public Throwable getLastError() {
141         return lastError;
142     }
143 
144     public void shutdown() {
145         try {
146             invoke("shutdown");
147         }
148         catch (Exception e) {
149             log.warn("Unable to shutdown the server", e);
150             lastError = e;
151         }
152     }
153 
154     //
155     // Kernel invocation helpers
156     //
157 
158     private Object invoke(final String operation, final Object[] args, final String[] signature) throws Exception {
159         assert operation != null;
160         assert args != null;
161         assert signature != null;
162 
163         return getConnection().invoke(Kernel.KERNEL, operation, args, signature);
164     }
165 
166     private Object invoke(final String operation, final Object[] args) throws Exception {
167         assert args != null;
168 
169         String[] signature = new String[args.length];
170         for (int i=0; i<args.length; i++) {
171             signature[i] = args[i].getClass().getName();
172         }
173 
174         return invoke(operation, args, signature);
175     }
176 
177     private Object invoke(final String operation) throws Exception {
178         return invoke(operation, new Object[0]);
179     }
180 
181     private Set listGBeans(final AbstractNameQuery query) throws Exception {
182         return (Set)invoke("listGBeans", new Object[] { query });
183     }
184 
185     private Object getAttribute(final AbstractName name, final String attribute) throws Exception {
186         assert name != null;
187         assert attribute != null;
188 
189         return invoke("getAttribute", new Object[] { name, attribute });
190     }
191 
192     private boolean getBooleanAttribute(final AbstractName name, final String attribute) throws Exception {
193         Object obj = getAttribute(name, attribute);
194         if (obj instanceof Boolean) {
195             return ((Boolean)obj).booleanValue();
196         }
197         else {
198             throw new RuntimeException("Attribute is not of type Boolean: " + attribute);
199         }
200     }
201 }