001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.servicemix.console;
018
019 import org.apache.commons.logging.Log;
020 import org.apache.commons.logging.LogFactory;
021 import org.apache.servicemix.jbi.audit.AuditorMBean;
022 import org.apache.servicemix.jbi.audit.jdbc.JdbcAuditor;
023 import org.apache.servicemix.jbi.container.JBIContainer;
024 import org.apache.servicemix.jbi.framework.DeploymentService;
025 import org.apache.servicemix.jbi.framework.InstallationService;
026 import org.apache.servicemix.jbi.management.ManagementContext;
027 import org.apache.servicemix.jbi.management.ManagementContextMBean;
028
029 import javax.jbi.management.DeploymentServiceMBean;
030 import javax.jbi.management.InstallationServiceMBean;
031 import javax.jbi.management.LifeCycleMBean;
032 import javax.management.MBeanServerConnection;
033 import javax.management.MBeanServerInvocationHandler;
034 import javax.management.ObjectName;
035 import javax.management.remote.JMXConnector;
036 import javax.management.remote.JMXConnectorFactory;
037 import javax.management.remote.JMXServiceURL;
038 import javax.portlet.ActionRequest;
039 import javax.portlet.ActionResponse;
040 import javax.portlet.GenericPortlet;
041 import javax.portlet.PortletConfig;
042 import javax.portlet.PortletContext;
043 import javax.portlet.PortletException;
044 import javax.portlet.PortletRequestDispatcher;
045 import javax.portlet.RenderRequest;
046 import javax.portlet.RenderResponse;
047 import javax.portlet.WindowState;
048 import javax.servlet.ServletContext;
049
050 import java.io.IOException;
051 import java.net.MalformedURLException;
052 import java.util.HashMap;
053 import java.util.Map;
054
055 public abstract class ServiceMixPortlet extends GenericPortlet {
056
057 protected final Log log = LogFactory.getLog(getClass());
058
059 protected PortletRequestDispatcher normalView;
060 protected PortletRequestDispatcher helpView;
061 protected PortletRequestDispatcher errorView;
062
063 private JMXConnector jmxConnector;
064 private String namingHost = "localhost";
065 private String containerName = JBIContainer.DEFAULT_NAME;
066 private String jmxDomainName = ManagementContext.DEFAULT_DOMAIN;
067 private String jmxUrl;
068 private int namingPort = ManagementContext.DEFAULT_CONNECTOR_PORT;
069 private String jndiPath = ManagementContext.DEFAULT_CONNECTOR_PATH;
070 private String username;
071 private String password;
072
073 /**
074 * Get the JMXServiceURL - built from the protocol used and host names
075 * @return the url
076 */
077 public JMXServiceURL getServiceURL() {
078 JMXServiceURL url = null;
079 if (url == null) {
080 try {
081 String jmxUrl = this.jmxUrl;
082 if (jmxUrl == null) {
083 jmxUrl = "service:jmx:rmi:///jndi/rmi://" + namingHost + ":" + namingPort + jndiPath;
084 }
085 url = new JMXServiceURL(jmxUrl);
086 }
087 catch (MalformedURLException e) {
088 log.error("error creating serviceURL: ", e);
089 }
090 }
091 return url;
092 }
093
094 /**
095 * Get a JMXConnector from a url
096 * @param url
097 * @return the JMXConnector
098 * @throws IOException
099 */
100 public JMXConnector getJMXConnector (JMXServiceURL url) throws IOException {
101 log.info("Connecting to JBI Container at: " + url);
102 String[] credentials = new String[] { username, password };
103 Map environment = new HashMap();
104 environment.put(JMXConnector.CREDENTIALS, credentials);
105 return JMXConnectorFactory.connect(url, environment);
106 }
107
108 protected void doHelp(RenderRequest renderRequest, RenderResponse renderResponse) throws PortletException, IOException {
109 log.debug("doHelp");
110 helpView.include(renderRequest, renderResponse);
111 }
112
113 protected void doView(RenderRequest renderRequest, RenderResponse renderResponse) throws PortletException, IOException {
114 log.debug("doView");
115 if (WindowState.MINIMIZED.equals(renderRequest.getWindowState())) {
116 return;
117 }
118 try {
119 // Retrieve the jmx connector
120 if (this.jmxConnector == null) {
121 this.jmxConnector = getJMXConnector(getServiceURL());
122 }
123 renderView(renderRequest, renderResponse);
124 } catch (PortletException e) {
125 log.error("Error rendering portlet", e);
126 closeConnector();
127 throw e;
128 } catch (IOException e) {
129 log.error("Error rendering portlet", e);
130 closeConnector();
131 throw e;
132 } catch (Exception e) {
133 try {
134 log.debug("Error rendering portlet", e);
135 renderRequest.setAttribute("exception", e);
136 errorView.include(renderRequest, renderResponse);
137 } finally {
138 closeConnector();
139 }
140 //log.error("Error rendering portlet", e);
141 //throw new PortletException("Error rendering portlet", e);
142 }
143 }
144
145 protected void renderView(RenderRequest renderRequest, RenderResponse renderResponse) throws Exception {
146 // Fill request
147 fillViewRequest(renderRequest);
148 // Render view
149 normalView.include(renderRequest, renderResponse);
150 }
151
152 /**
153 * Get a servicemix internal system management instance, from it's class name
154 * @param systemClass
155 * @return the object name
156 */
157 protected ObjectName getObjectName (Class systemClass){
158 return ManagementContext.getSystemObjectName(jmxDomainName, getContainerName(), systemClass);
159 }
160
161
162 protected void fillViewRequest(RenderRequest request) throws Exception {
163 }
164
165 public void init(PortletConfig portletConfig) throws PortletException {
166 log.debug("init");
167 super.init(portletConfig);
168 PortletContext pc = portletConfig.getPortletContext();
169 normalView = pc.getRequestDispatcher("/WEB-INF/view/" + getPortletName() + "/view.jsp");
170 helpView = pc.getRequestDispatcher("/WEB-INF/view/" + getPortletName() + "/help.jsp");
171 errorView = pc.getRequestDispatcher("/WEB-INF/view/error.jsp");
172
173 jmxUrl = getConfigString("servicemixJmxUrl", jmxUrl);
174 username = getConfigString("servicemixJmxUsername", username);
175 password = getConfigString("servicemixJmxPassword", password);
176 containerName = getConfigString("servicemixContainerName", containerName);
177 }
178
179 protected String getConfigString(String name, String defValue) {
180 ServletContext ctx = ContextLoaderListener.getServletContext();
181 if (ctx != null) {
182 String v = ctx.getInitParameter(name);
183 if (v != null) {
184 return v;
185 }
186 }
187 return defValue;
188 }
189
190 public void processAction(ActionRequest actionRequest, ActionResponse actionResponse) throws PortletException, IOException {
191 log.debug("processAction: " + actionRequest);
192 try {
193 // Retrieve the jmx connector
194 if (this.jmxConnector == null) {
195 this.jmxConnector = getJMXConnector(getServiceURL());
196 }
197 // Fill request
198 doProcessAction(actionRequest, actionResponse);
199 } catch (PortletException e) {
200 log.error("Error processing action", e);
201 closeConnector();
202 throw e;
203 } catch (IOException e) {
204 log.error("Error processing action", e);
205 closeConnector();
206 throw e;
207 } catch (Exception e) {
208 log.error("Error processing action", e);
209 closeConnector();
210 throw new PortletException("Error processing action", e);
211 }
212 }
213
214 protected void doProcessAction(ActionRequest actionRequest, ActionResponse actionResponse) throws Exception {
215 }
216
217 public void destroy() {
218 closeConnector();
219 super.destroy();
220 }
221
222 protected void closeConnector() {
223 if (this.jmxConnector != null){
224 try {
225 jmxConnector.close();
226 } catch (Exception e) {
227 log.warn("caught an error closing the jmxConnector", e);
228 } finally {
229 jmxConnector = null;
230 }
231 }
232 }
233
234 /**
235 * Get the InstallationServiceMBean
236 * @return the installation service MBean
237 * @throws IOException
238 */
239 public InstallationServiceMBean getInstallationService() throws IOException {
240 ObjectName objectName = getObjectName(InstallationService.class);
241 return (InstallationServiceMBean) getProxy(objectName, InstallationServiceMBean.class);
242 }
243
244 /**
245 * Get the DeploymentServiceMBean
246 * @return the deployment service mbean
247 * @throws IOException
248 */
249 public DeploymentServiceMBean getDeploymentService() throws IOException {
250 ObjectName objectName = getObjectName(DeploymentService.class);
251 return (DeploymentServiceMBean) getProxy(objectName, DeploymentServiceMBean.class);
252 }
253
254
255 /**
256 * Get the ManagementContextMBean
257 * @return the management service mbean
258 * @throws IOException
259 */
260 public ManagementContextMBean getManagementContext() throws IOException {
261 ObjectName objectName = getObjectName(ManagementContext.class);
262 return (ManagementContextMBean) getProxy(objectName, ManagementContextMBean.class);
263 }
264
265 public AuditorMBean getJdbcAuditor() throws IOException {
266 ObjectName objectName = getObjectName(JdbcAuditor.class);
267 return (AuditorMBean) getProxy(objectName, AuditorMBean.class);
268 }
269
270 public LifeCycleMBean getJBIContainer() throws IOException {
271 ObjectName objectName = ManagementContext.getContainerObjectName(jmxDomainName, containerName);
272 return (LifeCycleMBean) getProxy(objectName, LifeCycleMBean.class);
273 }
274
275 public Object getProxy(ObjectName name, Class type) throws IOException {
276 return MBeanServerInvocationHandler.newProxyInstance(getServerConnection(), name, type, true);
277 }
278
279 public MBeanServerConnection getServerConnection() throws IOException {
280 return jmxConnector.getMBeanServerConnection();
281 }
282
283 public String getContainerName() {
284 return containerName;
285 }
286
287 public void setContainerName(String containerName) {
288 this.containerName = containerName;
289 }
290
291 /**
292 * @return the password
293 */
294 protected String getPassword() {
295 return password;
296 }
297
298 /**
299 * @param password the password to set
300 */
301 protected void setPassword(String password) {
302 this.password = password;
303 }
304
305 /**
306 * @return the username
307 */
308 protected String getUsername() {
309 return username;
310 }
311
312 /**
313 * @param username the username to set
314 */
315 protected void setUsername(String username) {
316 this.username = username;
317 }
318
319 }