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 018 package org.apache.geronimo.console.configmanager; 019 020 import java.io.IOException; 021 import java.io.Serializable; 022 import java.util.ArrayList; 023 import java.util.Collections; 024 import java.util.HashMap; 025 import java.util.Iterator; 026 import java.util.List; 027 import java.util.Map; 028 import java.util.Set; 029 030 import javax.portlet.ActionRequest; 031 import javax.portlet.ActionResponse; 032 import javax.portlet.PortletConfig; 033 import javax.portlet.PortletException; 034 import javax.portlet.PortletRequestDispatcher; 035 import javax.portlet.RenderRequest; 036 import javax.portlet.RenderResponse; 037 import javax.portlet.WindowState; 038 039 import org.apache.geronimo.console.BasePortlet; 040 import org.apache.geronimo.console.util.PortletManager; 041 import org.apache.geronimo.gbean.AbstractName; 042 import org.apache.geronimo.gbean.AbstractNameQuery; 043 import org.apache.geronimo.kernel.DependencyManager; 044 import org.apache.geronimo.kernel.Kernel; 045 import org.apache.geronimo.kernel.KernelRegistry; 046 import org.apache.geronimo.kernel.config.Configuration; 047 import org.apache.geronimo.kernel.config.ConfigurationInfo; 048 import org.apache.geronimo.kernel.config.ConfigurationManager; 049 import org.apache.geronimo.kernel.config.ConfigurationModuleType; 050 import org.apache.geronimo.kernel.config.ConfigurationUtil; 051 import org.apache.geronimo.kernel.config.InvalidConfigException; 052 import org.apache.geronimo.kernel.config.LifecycleException; 053 import org.apache.geronimo.kernel.config.LifecycleResults; 054 import org.apache.geronimo.kernel.config.NoSuchConfigException; 055 import org.apache.geronimo.kernel.management.State; 056 import org.apache.geronimo.kernel.repository.Artifact; 057 import org.apache.geronimo.kernel.repository.MissingDependencyException; 058 import org.apache.geronimo.management.geronimo.WebModule; 059 import org.apache.commons.logging.Log; 060 import org.apache.commons.logging.LogFactory; 061 062 /** 063 * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $ 064 */ 065 public class ConfigManagerPortlet extends BasePortlet { 066 private final static Log log = LogFactory.getLog(ConfigManagerPortlet.class); 067 068 private static final String START_ACTION = "start"; 069 070 private static final String STOP_ACTION = "stop"; 071 072 private static final String RESTART_ACTION = "restart"; 073 074 private static final String UNINSTALL_ACTION = "uninstall"; 075 076 private static final String CONFIG_INIT_PARAM = "config-type"; 077 078 private static final String SHOW_DEPENDENCIES_COOKIE = "org.apache.geronimo.configmanager.showDependencies"; 079 080 private Kernel kernel; 081 082 private PortletRequestDispatcher normalView; 083 084 private PortletRequestDispatcher maximizedView; 085 086 private PortletRequestDispatcher helpView; 087 088 private static List loadChildren(Kernel kernel, String configName) { 089 List<String> kids = new ArrayList<String>(); 090 091 Map<String, String> filter = new HashMap<String, String>(); 092 filter.put("J2EEApplication", configName); 093 filter.put("j2eeType", "WebModule"); 094 095 Set<AbstractName> test = kernel.listGBeans(new AbstractNameQuery(null, filter)); 096 for (AbstractName child : test) { 097 String childName = child.getNameProperty("name"); 098 kids.add(childName); 099 } 100 101 filter.put("j2eeType", "EJBModule"); 102 test = kernel.listGBeans(new AbstractNameQuery(null, filter)); 103 for (AbstractName child : test) { 104 String childName = child.getNameProperty("name"); 105 kids.add(childName); 106 } 107 108 filter.put("j2eeType", "AppClientModule"); 109 test = kernel.listGBeans(new AbstractNameQuery(null, filter)); 110 for (AbstractName child : test) { 111 String childName = child.getNameProperty("name"); 112 kids.add(childName); 113 } 114 115 filter.put("j2eeType", "ResourceAdapterModule"); 116 test = kernel.listGBeans(new AbstractNameQuery(null, filter)); 117 for (AbstractName child : test) { 118 String childName = child.getNameProperty("name"); 119 kids.add(childName); 120 } 121 return kids; 122 } 123 124 public void printResults(Set<Artifact> lcresult, StringBuffer buf) { 125 for (Artifact config : lcresult) { 126 127 //TODO might be a hack 128 List<String> kidsChild = loadChildren(kernel, config.toString()); 129 130 //TODO figure out the web url and show it when appropriate. 131 buf.append(" ").append(config).append("<br />"); 132 for (String kid: kidsChild) { 133 buf.append(" `-> ").append(kid).append("<br />"); 134 } 135 buf.append("<br />"); 136 } 137 } 138 139 public void processAction(ActionRequest actionRequest, ActionResponse actionResponse) throws PortletException, IOException { 140 String action = actionRequest.getParameter("action"); 141 actionResponse.setRenderParameter("message", ""); // set to blank first 142 try { 143 ConfigurationManager configurationManager = ConfigurationUtil.getConfigurationManager(kernel); 144 String config = getConfigID(actionRequest); 145 Artifact configId = Artifact.create(config); 146 147 if (START_ACTION.equals(action)) { 148 if(!configurationManager.isLoaded(configId)) { 149 configurationManager.loadConfiguration(configId); 150 } 151 if(!configurationManager.isRunning(configId)) { 152 org.apache.geronimo.kernel.config.LifecycleResults lcresult = configurationManager.startConfiguration(configId); 153 message(actionResponse, lcresult, "Started application<br /><br />"); 154 } 155 } else if (STOP_ACTION.equals(action)) { 156 if(configurationManager.isRunning(configId)) { 157 configurationManager.stopConfiguration(configId); 158 } 159 if(configurationManager.isLoaded(configId)) { 160 LifecycleResults lcresult = configurationManager.unloadConfiguration(configId); 161 message(actionResponse, lcresult, "Stopped application<br /><br />"); 162 } 163 } else if (UNINSTALL_ACTION.equals(action)) { 164 configurationManager.uninstallConfiguration(configId); 165 message(actionResponse, null, "Uninstalled application<br /><br />"+configId+"<br /><br />"); 166 } else if (RESTART_ACTION.equals(action)) { 167 LifecycleResults lcresult = configurationManager.restartConfiguration(configId); 168 message(actionResponse, lcresult, "Restarted application<br /><br />"); 169 } else { 170 message(actionResponse, null, "Invalid value for changeState: " + action + "<br /><br />"); 171 throw new PortletException("Invalid value for changeState: " + action); 172 } 173 } catch (NoSuchConfigException e) { 174 // ignore this for now 175 message(actionResponse, null, "Configuration not found<br /><br />"); 176 log.error("Configuration not found", e); 177 } catch (LifecycleException e) { 178 // todo we have a much more detailed report now 179 message(actionResponse, null, "Lifecycle operation failed<br /><br />"); 180 log.error("Lifecycle operation failed ", e); 181 } catch (Exception e) { 182 message(actionResponse, null, "Encountered an unhandled exception<br /><br />"); 183 log.error("Exception", e); 184 } 185 } 186 187 private void message(ActionResponse actionResponse, LifecycleResults lcresult, String str) { 188 StringBuffer buf = new StringBuffer(str); 189 if (lcresult != null) { 190 this.printResults(lcresult.getStarted(), buf); 191 } 192 actionResponse.setRenderParameter("messageStatus", buf.toString()); 193 } 194 195 /** 196 * Check if a configuration should be listed here. This method depends on the "config-type" portlet parameter 197 * which is set in portle.xml. 198 */ 199 private boolean shouldListConfig(ConfigurationModuleType info) { 200 String configType = getInitParameter(CONFIG_INIT_PARAM); 201 return configType == null || info.getName().equalsIgnoreCase(configType); 202 } 203 204 private String getConfigID(ActionRequest actionRequest) { 205 return actionRequest.getParameter("configId"); 206 } 207 208 protected void doView(RenderRequest renderRequest, RenderResponse renderResponse) throws IOException, PortletException { 209 if (WindowState.MINIMIZED.equals(renderRequest.getWindowState())) { 210 return; 211 } 212 213 String cookies = renderRequest.getProperty("cookie"); 214 boolean showDependencies = (cookies != null && cookies.indexOf(SHOW_DEPENDENCIES_COOKIE + "=true") > 0); 215 216 List<ModuleDetails> moduleDetails = new ArrayList<ModuleDetails>(); 217 ConfigurationManager configManager = ConfigurationUtil.getConfigurationManager(kernel); 218 List<ConfigurationInfo> infos = configManager.listConfigurations(); 219 for (ConfigurationInfo info : infos) { 220 221 String moduleType = getInitParameter(CONFIG_INIT_PARAM); 222 if (ConfigurationModuleType.WAR.getName().equalsIgnoreCase(moduleType)) { 223 224 if (info.getType().getValue() == ConfigurationModuleType.WAR.getValue()) { 225 ModuleDetails details = new ModuleDetails(info.getConfigID(), info.getType(), info.getState()); 226 try { 227 AbstractName configObjName = Configuration.getConfigurationAbstractName(info.getConfigID()); 228 boolean loaded = loadModule(configManager, configObjName); 229 230 WebModule webModule = (WebModule) PortletManager.getModule(renderRequest, info.getConfigID()); 231 if (webModule != null) { 232 details.getContextPaths().add(webModule.getContextPath()); 233 } 234 235 if (showDependencies) { 236 addDependencies(details, configObjName); 237 } 238 if (loaded) { 239 unloadModule(configManager, configObjName); 240 } 241 } catch (InvalidConfigException ice) { 242 // Should not occur 243 ice.printStackTrace(); 244 } 245 moduleDetails.add(details); 246 } else if (info.getType().getValue() == ConfigurationModuleType.EAR.getValue()) { 247 try { 248 AbstractName configObjName = Configuration.getConfigurationAbstractName(info.getConfigID()); 249 boolean loaded = loadModule(configManager, configObjName); 250 251 Configuration config = configManager.getConfiguration(info.getConfigID()); 252 if(config != null){ 253 for (Configuration child : config.getChildren()) { 254 if (child.getModuleType().getValue() == ConfigurationModuleType.WAR.getValue()) { 255 ModuleDetails childDetails = new ModuleDetails(info.getConfigID(), child.getModuleType(), info.getState()); 256 childDetails.setComponentName(child.getId().toString()); 257 WebModule webModule = getWebModule(config, child); 258 if (webModule != null) { 259 childDetails.getContextPaths().add(webModule.getContextPath()); 260 } 261 if (showDependencies) { 262 addDependencies(childDetails, configObjName); 263 } 264 moduleDetails.add(childDetails); 265 } 266 } 267 } 268 269 if (loaded) { 270 unloadModule(configManager, configObjName); 271 } 272 } catch (InvalidConfigException ice) { 273 // Should not occur 274 ice.printStackTrace(); 275 } 276 } 277 278 } else if (shouldListConfig(info.getType())) { 279 ModuleDetails details = new ModuleDetails(info.getConfigID(), info.getType(), info.getState()); 280 try { 281 AbstractName configObjName = Configuration.getConfigurationAbstractName(info.getConfigID()); 282 boolean loaded = loadModule(configManager, configObjName); 283 284 if (info.getType().getValue() == ConfigurationModuleType.EAR.getValue()) { 285 Configuration config = configManager.getConfiguration(info.getConfigID()); 286 if(config != null){ 287 Iterator childs = config.getChildren().iterator(); 288 while (childs.hasNext()) { 289 Configuration child = (Configuration) childs.next(); 290 if (child.getModuleType().getValue() == ConfigurationModuleType.WAR.getValue()) { 291 WebModule webModule = getWebModule(config, child); 292 if (webModule != null) { 293 details.getContextPaths().add(webModule.getContextPath()); 294 } 295 } 296 } 297 if (showDependencies) { 298 addDependencies(details, configObjName); 299 } 300 } 301 } 302 if (loaded) { 303 unloadModule(configManager, configObjName); 304 } 305 } catch (InvalidConfigException ice) { 306 // Should not occur 307 ice.printStackTrace(); 308 } 309 moduleDetails.add(details); 310 } 311 } 312 Collections.sort(moduleDetails); 313 renderRequest.setAttribute("configurations", moduleDetails); 314 renderRequest.setAttribute("showWebInfo", Boolean.valueOf(showWebInfo())); 315 renderRequest.setAttribute("showDependencies", Boolean.valueOf(showDependencies)); 316 if (moduleDetails.size() == 0) { 317 renderRequest.setAttribute("messageInstalled", "No modules found of this type<br /><br />"); 318 } else { 319 renderRequest.setAttribute("messageInstalled", ""); 320 } 321 renderRequest.setAttribute("messageStatus", renderRequest.getParameter("messageStatus")); 322 if (WindowState.NORMAL.equals(renderRequest.getWindowState())) { 323 normalView.include(renderRequest, renderResponse); 324 } else { 325 maximizedView.include(renderRequest, renderResponse); 326 } 327 } 328 329 private WebModule getWebModule(Configuration config, Configuration child) { 330 try { 331 Map<String, String> query1 = new HashMap<String, String>(); 332 String name = config.getId().getArtifactId(); 333 query1.put("J2EEApplication", config.getId().toString()); 334 query1.put("j2eeType", "WebModule"); 335 query1.put("name", child.getId().getArtifactId().substring(name.length()+1)); 336 AbstractName childName = new AbstractName(config.getAbstractName().getArtifact(), query1); 337 return (WebModule)kernel.getGBean(childName); 338 } catch(Exception h){ 339 // No gbean found, will not happen 340 // Except if module not started, ignored 341 } 342 return null; 343 } 344 345 private boolean loadModule(ConfigurationManager configManager, AbstractName configObjName) { 346 if(!kernel.isLoaded(configObjName)) { 347 try { 348 configManager.loadConfiguration(configObjName.getArtifact()); 349 return true; 350 } catch (NoSuchConfigException e) { 351 // Should not occur 352 e.printStackTrace(); 353 } catch (LifecycleException e) { 354 // config could not load because one or more of its dependencies 355 // has been removed. cannot load the configuration in this case, 356 // so don't rely on that technique to discover its parents or children 357 if (e.getCause() instanceof MissingDependencyException) { 358 // do nothing 359 } else { 360 e.printStackTrace(); 361 } 362 } 363 } 364 return false; 365 } 366 367 private void addDependencies(ModuleDetails details, AbstractName configObjName) { 368 DependencyManager depMgr = kernel.getDependencyManager(); 369 Set<AbstractName> parents = depMgr.getParents(configObjName); 370 for (AbstractName parent : parents) { 371 details.getParents().add(parent.getArtifact()); 372 } 373 Set<AbstractName> children = depMgr.getChildren(configObjName); 374 for (AbstractName child : children) { 375 //if(configManager.isConfiguration(child.getArtifact())) 376 if (child.getNameProperty("configurationName") != null) { 377 details.getChildren().add(child.getArtifact()); 378 } 379 } 380 Collections.sort(details.getParents()); 381 Collections.sort(details.getChildren()); 382 } 383 384 private void unloadModule(ConfigurationManager configManager, AbstractName configObjName) { 385 try { 386 configManager.unloadConfiguration(configObjName.getArtifact()); 387 } catch (NoSuchConfigException e) { 388 // Should not occur 389 e.printStackTrace(); 390 } 391 } 392 393 private boolean showWebInfo() { 394 String moduleType = getInitParameter(CONFIG_INIT_PARAM); 395 return ConfigurationModuleType.WAR.getName().equalsIgnoreCase(moduleType) || 396 ConfigurationModuleType.EAR.getName().equalsIgnoreCase(moduleType); 397 } 398 399 protected void doHelp(RenderRequest renderRequest, RenderResponse renderResponse) throws PortletException, IOException { 400 helpView.include(renderRequest, renderResponse); 401 } 402 403 public void init(PortletConfig portletConfig) throws PortletException { 404 super.init(portletConfig); 405 kernel = KernelRegistry.getSingleKernel(); 406 normalView = portletConfig.getPortletContext().getRequestDispatcher("/WEB-INF/view/configmanager/normal.jsp"); 407 maximizedView = portletConfig.getPortletContext().getRequestDispatcher("/WEB-INF/view/configmanager/maximized.jsp"); 408 helpView = portletConfig.getPortletContext().getRequestDispatcher("/WEB-INF/view/configmanager/help.jsp"); 409 } 410 411 public void destroy() { 412 normalView = null; 413 maximizedView = null; 414 kernel = null; 415 super.destroy(); 416 } 417 418 /** 419 * Convenience data holder for portlet that displays deployed modules. 420 * Includes context path information for web modules. 421 */ 422 public static class ModuleDetails implements Comparable, Serializable { 423 private static final long serialVersionUID = -7022687152297202079L; 424 private final Artifact configId; 425 private final ConfigurationModuleType type; 426 private final State state; 427 private List<Artifact> parents = new ArrayList<Artifact>(); 428 private List<Artifact> children = new ArrayList<Artifact>(); 429 private boolean expertConfig = false; // used to mark this config as one that should only be managed (stop/uninstall) by expert users. 430 private List<String> contextPaths = new ArrayList<String>(); 431 private String componentName; 432 433 public ModuleDetails(Artifact configId, ConfigurationModuleType type, State state) { 434 this.configId = configId; 435 this.type = type; 436 this.state = state; 437 if (configId.toString().indexOf("org.apache.geronimo.configs/") == 0) { 438 this.expertConfig = true; 439 } 440 } 441 442 public int compareTo(Object o) { 443 if (o != null && o instanceof ModuleDetails){ 444 return configId.compareTo(((ModuleDetails)o).configId); 445 } else { 446 return -1; 447 } 448 } 449 450 public Artifact getConfigId() { 451 return configId; 452 } 453 454 public State getState() { 455 return state; 456 } 457 458 public ConfigurationModuleType getType() { 459 return type; 460 } 461 462 public boolean getExpertConfig() { 463 return expertConfig; 464 } 465 466 public List<Artifact> getParents() { 467 return parents; 468 } 469 470 public List<Artifact> getChildren() { 471 return children; 472 } 473 474 public List<String> getContextPaths() { 475 return contextPaths; 476 } 477 478 public String getComponentName(){ 479 return componentName; 480 } 481 482 public void setComponentName(String name){ 483 componentName = name; 484 } 485 } 486 }