1 /** 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package org.apache.geronimo.console.configmanager; 19 20 import java.io.IOException; 21 import java.io.Serializable; 22 import java.util.ArrayList; 23 import java.util.Collections; 24 import java.util.HashMap; 25 import java.util.Iterator; 26 import java.util.List; 27 import java.util.Map; 28 import java.util.Set; 29 30 import javax.portlet.ActionRequest; 31 import javax.portlet.ActionResponse; 32 import javax.portlet.PortletConfig; 33 import javax.portlet.PortletException; 34 import javax.portlet.PortletRequestDispatcher; 35 import javax.portlet.RenderRequest; 36 import javax.portlet.RenderResponse; 37 import javax.portlet.WindowState; 38 39 import org.apache.geronimo.console.BasePortlet; 40 import org.apache.geronimo.console.util.PortletManager; 41 import org.apache.geronimo.gbean.AbstractName; 42 import org.apache.geronimo.gbean.AbstractNameQuery; 43 import org.apache.geronimo.gbean.GBeanData; 44 import org.apache.geronimo.kernel.DependencyManager; 45 import org.apache.geronimo.kernel.InternalKernelException; 46 import org.apache.geronimo.kernel.Kernel; 47 import org.apache.geronimo.kernel.KernelRegistry; 48 import org.apache.geronimo.kernel.config.Configuration; 49 import org.apache.geronimo.kernel.config.ConfigurationInfo; 50 import org.apache.geronimo.kernel.config.ConfigurationManager; 51 import org.apache.geronimo.kernel.config.ConfigurationModuleType; 52 import org.apache.geronimo.kernel.config.ConfigurationUtil; 53 import org.apache.geronimo.kernel.config.InvalidConfigException; 54 import org.apache.geronimo.kernel.config.LifecycleException; 55 import org.apache.geronimo.kernel.config.LifecycleResults; 56 import org.apache.geronimo.kernel.config.NoSuchConfigException; 57 import org.apache.geronimo.kernel.management.State; 58 import org.apache.geronimo.kernel.repository.Artifact; 59 import org.apache.geronimo.kernel.repository.MissingDependencyException; 60 import org.apache.geronimo.management.geronimo.WebModule; 61 import org.slf4j.Logger; 62 import org.slf4j.LoggerFactory; 63 64 public class ConfigManagerPortlet extends BasePortlet { 65 66 private static final Logger logger = LoggerFactory.getLogger(ConfigManagerPortlet.class); 67 68 private static final String START_ACTION = "start"; 69 70 private static final String STOP_ACTION = "stop"; 71 72 private static final String RESTART_ACTION = "restart"; 73 74 private static final String UNINSTALL_ACTION = "uninstall"; 75 76 private static final String CONFIG_INIT_PARAM = "config-type"; 77 78 private static final String SHOW_DEPENDENCIES_COOKIE = "org.apache.geronimo.configmanager.showDependencies"; 79 80 private Kernel kernel; 81 82 private PortletRequestDispatcher normalView; 83 84 private PortletRequestDispatcher maximizedView; 85 86 private PortletRequestDispatcher helpView; 87 88 private boolean showDisplayName; 89 90 private String moduleType; 91 92 private static List<String> loadChildren(Kernel kernel, String configName) { 93 List<String> kids = new ArrayList<String>(); 94 95 Map<String, String> filter = new HashMap<String, String>(); 96 filter.put("J2EEApplication", configName); 97 filter.put("j2eeType", "WebModule"); 98 99 Set<AbstractName> test = kernel.listGBeans(new AbstractNameQuery(null, filter)); 100 for (AbstractName child : test) { 101 String childName = child.getNameProperty("name"); 102 kids.add(childName); 103 } 104 105 filter.put("j2eeType", "EJBModule"); 106 test = kernel.listGBeans(new AbstractNameQuery(null, filter)); 107 for (AbstractName child : test) { 108 String childName = child.getNameProperty("name"); 109 kids.add(childName); 110 } 111 112 filter.put("j2eeType", "AppClientModule"); 113 test = kernel.listGBeans(new AbstractNameQuery(null, filter)); 114 for (AbstractName child : test) { 115 String childName = child.getNameProperty("name"); 116 kids.add(childName); 117 } 118 119 filter.put("j2eeType", "ResourceAdapterModule"); 120 test = kernel.listGBeans(new AbstractNameQuery(null, filter)); 121 for (AbstractName child : test) { 122 String childName = child.getNameProperty("name"); 123 kids.add(childName); 124 } 125 return kids; 126 } 127 128 public String printResults(Set<Artifact> lcresult) { 129 StringBuilder sb = new StringBuilder(); 130 for (Artifact config : lcresult) { 131 132 // TODO might be a hack 133 List<String> kidsChild = loadChildren(kernel, config.toString()); 134 135 // TODO figure out the web url and show it when appropriate. 136 sb.append("<br />").append(config); 137 for (String kid : kidsChild) { 138 sb.append("<br />-> ").append(kid); 139 } 140 } 141 return sb.toString(); 142 } 143 144 public void processAction(ActionRequest actionRequest, ActionResponse actionResponse) throws PortletException, IOException { 145 String action = actionRequest.getParameter("action"); 146 actionResponse.setRenderParameter("message", ""); // set to blank first 147 try { 148 ConfigurationManager configurationManager = ConfigurationUtil.getConfigurationManager(kernel); 149 String config = getConfigID(actionRequest); 150 Artifact configId = Artifact.create(config); 151 152 if (START_ACTION.equals(action)) { 153 if(!configurationManager.isLoaded(configId)) { 154 configurationManager.loadConfiguration(configId); 155 } 156 if(!configurationManager.isRunning(configId)) { 157 org.apache.geronimo.kernel.config.LifecycleResults lcresult = configurationManager.startConfiguration(configId); 158 addInfoMessage(actionRequest, getLocalizedString(actionRequest, "consolebase.infoMsg01") + printResults(lcresult.getStarted())); 159 } 160 } else if (STOP_ACTION.equals(action)) { 161 if(configurationManager.isLoaded(configId)) { 162 LifecycleResults lcresult = configurationManager.unloadConfiguration(configId); 163 addInfoMessage(actionRequest, getLocalizedString(actionRequest, "consolebase.infoMsg02") + printResults(lcresult.getStopped())); 164 } 165 } else if (UNINSTALL_ACTION.equals(action)) { 166 configurationManager.uninstallConfiguration(configId); 167 addInfoMessage(actionRequest, getLocalizedString(actionRequest, "consolebase.infoMsg04") + "<br />" + configId); 168 } else if (RESTART_ACTION.equals(action)) { 169 LifecycleResults lcresult = configurationManager.restartConfiguration(configId); 170 addInfoMessage(actionRequest, getLocalizedString(actionRequest, "consolebase.infoMsg03") + printResults(lcresult.getStarted())); 171 } else { 172 addWarningMessage(actionRequest, getLocalizedString(actionRequest, "consolebase.warnMsg01") + action + "<br />"); 173 throw new PortletException("Invalid value for changeState: " + action); 174 } 175 } catch (NoSuchConfigException e) { 176 // ignore this for now 177 addErrorMessage(actionRequest, getLocalizedString(actionRequest, "consolebase.errorMsg01")); 178 logger.error("Configuration not found", e); 179 } catch (LifecycleException e) { 180 // todo we have a much more detailed report now 181 addErrorMessage(actionRequest, getLocalizedString(actionRequest, "consolebase.errorMsg02")); 182 logger.error("Lifecycle operation failed ", e); 183 } catch (Throwable e) { 184 addErrorMessage(actionRequest, getLocalizedString(actionRequest, "consolebase.errorMsg03")); 185 logger.error("Exception", e); 186 } 187 } 188 189 /** 190 * Check if a configuration should be listed here. This method depends on the "config-type" portlet parameter 191 * which is set in portle.xml. 192 */ 193 private boolean shouldListConfig(ConfigurationModuleType info) { 194 String configType = getInitParameter(CONFIG_INIT_PARAM); 195 return configType == null || info.getName().equalsIgnoreCase(configType); 196 } 197 198 private String getConfigID(ActionRequest actionRequest) { 199 return actionRequest.getParameter("configId"); 200 } 201 202 protected void doView(RenderRequest renderRequest, RenderResponse renderResponse) throws IOException, PortletException { 203 if (WindowState.MINIMIZED.equals(renderRequest.getWindowState())) { 204 return; 205 } 206 207 String cookies = renderRequest.getProperty("cookie"); 208 boolean showDependencies = (cookies != null && cookies.indexOf(SHOW_DEPENDENCIES_COOKIE + "=true") > 0); 209 210 List<ModuleDetails> moduleDetails = new ArrayList<ModuleDetails>(); 211 ConfigurationManager configManager = ConfigurationUtil.getConfigurationManager(kernel); 212 List<ConfigurationInfo> infos = configManager.listConfigurations(); 213 for (ConfigurationInfo info : infos) { 214 if (ConfigurationModuleType.WAR.getName().equalsIgnoreCase(moduleType)) { 215 216 if (info.getType().getValue() == ConfigurationModuleType.WAR.getValue()) { 217 ModuleDetails details = new ModuleDetails(info.getConfigID(), info.getType(), info.getState()); 218 try { 219 AbstractName configObjName = Configuration.getConfigurationAbstractName(info.getConfigID()); 220 boolean loaded = loadModule(configManager, configObjName); 221 222 WebModule webModule = (WebModule) PortletManager.getModule(renderRequest, info.getConfigID()); 223 224 if (webModule != null) { 225 details.getContextPaths().add(webModule.getContextPath()); 226 details.setDisplayName(webModule.getDisplayName()); 227 } 228 229 if (showDependencies) { 230 addDependencies(details, configObjName); 231 } 232 233 if (loaded) { 234 unloadModule(configManager, configObjName); 235 } 236 } catch (InvalidConfigException ice) { 237 // Should not occur 238 ice.printStackTrace(); 239 } 240 moduleDetails.add(details); 241 } else if (info.getType().getValue() == ConfigurationModuleType.EAR.getValue()) { 242 try { 243 AbstractName configObjName = Configuration.getConfigurationAbstractName(info.getConfigID()); 244 boolean loaded = loadModule(configManager, configObjName); 245 246 Configuration config = configManager.getConfiguration(info.getConfigID()); 247 if(config != null){ 248 for (Configuration child : config.getChildren()) { 249 if (child.getModuleType().getValue() == ConfigurationModuleType.WAR.getValue()) { 250 ModuleDetails childDetails = new ModuleDetails(info.getConfigID(), child.getModuleType(), info.getState()); 251 childDetails.setComponentName(child.getId().toString()); 252 WebModule webModule = getWebModule(config, child); 253 if (webModule != null) { 254 childDetails.getContextPaths().add(webModule.getContextPath()); 255 childDetails.setDisplayName(webModule.getDisplayName()); 256 } 257 if (showDependencies) { 258 addDependencies(childDetails, configObjName); 259 } 260 moduleDetails.add(childDetails); 261 } 262 } 263 } 264 265 if (loaded) { 266 unloadModule(configManager, configObjName); 267 } 268 } catch (InvalidConfigException ice) { 269 // Should not occur 270 ice.printStackTrace(); 271 } 272 } 273 274 } else if (shouldListConfig(info.getType())) { 275 ModuleDetails details = new ModuleDetails(info.getConfigID(), info.getType(), getConfigurationState(info)); 276 try { 277 AbstractName configObjName = Configuration.getConfigurationAbstractName(info.getConfigID()); 278 boolean loaded = loadModule(configManager, configObjName); 279 280 if (info.getType().getValue() == ConfigurationModuleType.EAR.getValue()) { 281 Configuration config = configManager.getConfiguration(info.getConfigID()); 282 if(config != null){ 283 Iterator childs = config.getChildren().iterator(); 284 while (childs.hasNext()) { 285 Configuration child = (Configuration) childs.next(); 286 if (child.getModuleType().getValue() == ConfigurationModuleType.WAR.getValue()) { 287 WebModule webModule = getWebModule(config, child); 288 if (webModule != null) { 289 details.getContextPaths().add(webModule.getContextPath()); 290 } 291 } 292 } 293 } 294 } else if (info.getType().equals(ConfigurationModuleType.CAR)) { 295 Configuration config = configManager.getConfiguration(info.getConfigID()); 296 details.setClientAppServerSide(config.getOwnedConfigurations().size() > 0); 297 } 298 if (showDependencies) { 299 addDependencies(details, configObjName); 300 } 301 if (loaded) { 302 unloadModule(configManager, configObjName); 303 } 304 } catch (InvalidConfigException ice) { 305 // Should not occur 306 ice.printStackTrace(); 307 } 308 moduleDetails.add(details); 309 } 310 } 311 Collections.sort(moduleDetails); 312 renderRequest.setAttribute("configurations", moduleDetails); 313 renderRequest.setAttribute("showWebInfo", Boolean.valueOf(showWebInfo())); 314 renderRequest.setAttribute("showDisplayName", Boolean.valueOf(showDisplayName)); 315 renderRequest.setAttribute("showDependencies", Boolean.valueOf(showDependencies)); 316 if (moduleDetails.size() == 0) { 317 addWarningMessage(renderRequest, getLocalizedString(renderRequest, "consolebase.warnMsg02")); 318 } 319 if (WindowState.NORMAL.equals(renderRequest.getWindowState())) { 320 normalView.include(renderRequest, renderResponse); 321 } else { 322 maximizedView.include(renderRequest, renderResponse); 323 } 324 } 325 326 private State getConfigurationState(ConfigurationInfo configurationInfo) { 327 State configurationState = configurationInfo.getState(); 328 if (configurationState.isRunning()) { 329 // Check whether the Configuration's sub-gbeans are running 330 try { 331 Configuration configuration = PortletManager.getConfigurationManager().getConfiguration(configurationInfo.getConfigID()); 332 Map<AbstractName, GBeanData> abstractNameGBeanDataMap = configuration.getGBeans(); 333 // Check one sub-GBean's state, if one gbean fails to start, all will be shutdown 334 Iterator<AbstractName> it = abstractNameGBeanDataMap.keySet().iterator(); 335 if (it.hasNext()) { 336 AbstractName abstractName = it.next(); 337 if (!PortletManager.getKernel().isRunning(abstractName)) { 338 return State.STOPPED; 339 } 340 } 341 } catch (InternalKernelException e) { 342 return State.STOPPED; 343 } catch (IllegalStateException e) { 344 return State.STOPPED; 345 } 346 } 347 return configurationState; 348 } 349 350 private WebModule getWebModule(Configuration config, Configuration child) { 351 try { 352 Map<String, String> query1 = new HashMap<String, String>(); 353 String name = config.getId().getArtifactId(); 354 query1.put("J2EEApplication", config.getId().toString()); 355 query1.put("j2eeType", "WebModule"); 356 query1.put("name", child.getId().getArtifactId().substring(name.length()+1)); 357 AbstractName childName = new AbstractName(config.getAbstractName().getArtifact(), query1); 358 return (WebModule)kernel.getGBean(childName); 359 } catch(Exception h){ 360 // No gbean found, will not happen 361 // Except if module not started, ignored 362 } 363 return null; 364 } 365 366 private boolean loadModule(ConfigurationManager configManager, AbstractName configObjName) { 367 if(!kernel.isLoaded(configObjName)) { 368 try { 369 configManager.loadConfiguration(configObjName.getArtifact()); 370 return true; 371 } catch (NoSuchConfigException e) { 372 // Should not occur 373 e.printStackTrace(); 374 } catch (LifecycleException e) { 375 // config could not load because one or more of its dependencies 376 // has been removed. cannot load the configuration in this case, 377 // so don't rely on that technique to discover its parents or children 378 if (e.getCause() instanceof MissingDependencyException) { 379 // do nothing 380 } else { 381 e.printStackTrace(); 382 } 383 } 384 } 385 return false; 386 } 387 388 private void addDependencies(ModuleDetails details, AbstractName configObjName) { 389 DependencyManager depMgr = kernel.getDependencyManager(); 390 Set<AbstractName> parents = depMgr.getParents(configObjName); 391 for (AbstractName parent : parents) { 392 details.getParents().add(parent.getArtifact()); 393 } 394 Set<AbstractName> children = depMgr.getChildren(configObjName); 395 for (AbstractName child : children) { 396 //if(configManager.isConfiguration(child.getArtifact())) 397 if (child.getNameProperty("configurationName") != null) { 398 details.getChildren().add(child.getArtifact()); 399 } 400 } 401 Collections.sort(details.getParents()); 402 Collections.sort(details.getChildren()); 403 } 404 405 private void unloadModule(ConfigurationManager configManager, AbstractName configObjName) { 406 try { 407 configManager.unloadConfiguration(configObjName.getArtifact()); 408 } catch (NoSuchConfigException e) { 409 // Should not occur 410 e.printStackTrace(); 411 } 412 } 413 414 private boolean showWebInfo() { 415 return ConfigurationModuleType.WAR.getName().equalsIgnoreCase(moduleType) || 416 ConfigurationModuleType.EAR.getName().equalsIgnoreCase(moduleType); 417 } 418 419 protected void doHelp(RenderRequest renderRequest, RenderResponse renderResponse) throws PortletException, IOException { 420 helpView.include(renderRequest, renderResponse); 421 } 422 423 public void init(PortletConfig portletConfig) throws PortletException { 424 super.init(portletConfig); 425 kernel = KernelRegistry.getSingleKernel(); 426 normalView = portletConfig.getPortletContext().getRequestDispatcher("/WEB-INF/view/configmanager/normal.jsp"); 427 maximizedView = portletConfig.getPortletContext().getRequestDispatcher("/WEB-INF/view/configmanager/maximized.jsp"); 428 helpView = portletConfig.getPortletContext().getRequestDispatcher("/WEB-INF/view/configmanager/help.jsp"); 429 moduleType = getInitParameter(CONFIG_INIT_PARAM); 430 //Only show the displayNames for the web applications 431 showDisplayName = ConfigurationModuleType.WAR.getName().equalsIgnoreCase(moduleType); 432 } 433 434 public void destroy() { 435 normalView = null; 436 maximizedView = null; 437 kernel = null; 438 super.destroy(); 439 } 440 441 /** 442 * Convenience data holder for portlet that displays deployed modules. 443 * Includes context path information for web modules. 444 */ 445 public static class ModuleDetails implements Comparable, Serializable { 446 private static final long serialVersionUID = -7022687152297202079L; 447 private final Artifact configId; 448 private final ConfigurationModuleType type; 449 private final State state; 450 private List<Artifact> parents = new ArrayList<Artifact>(); 451 private List<Artifact> children = new ArrayList<Artifact>(); 452 private boolean expertConfig = false; // used to mark this config as one that should only be managed (stop/uninstall) by expert users. 453 private List<String> contextPaths = new ArrayList<String>(); 454 private String componentName; 455 //This flag is used to indicate whether it is the client side if the module is a client application 456 private boolean clientAppServerSide = false; 457 private String displayName; 458 459 public ModuleDetails(Artifact configId, ConfigurationModuleType type, State state) { 460 this.configId = configId; 461 this.type = type; 462 this.state = state; 463 if (configId.toString().indexOf("org.apache.geronimo.configs/") == 0) { 464 this.expertConfig = true; 465 } 466 } 467 468 public int compareTo(Object o) { 469 if (o != null && o instanceof ModuleDetails){ 470 return configId.compareTo(((ModuleDetails)o).configId); 471 } else { 472 return -1; 473 } 474 } 475 476 public Artifact getConfigId() { 477 return configId; 478 } 479 480 public State getState() { 481 return state; 482 } 483 484 public ConfigurationModuleType getType() { 485 return type; 486 } 487 488 public boolean getExpertConfig() { 489 return expertConfig; 490 } 491 492 public List<Artifact> getParents() { 493 return parents; 494 } 495 496 public List<Artifact> getChildren() { 497 return children; 498 } 499 500 public List<String> getContextPaths() { 501 return contextPaths; 502 } 503 504 public String getComponentName(){ 505 return componentName; 506 } 507 508 public void setComponentName(String name){ 509 componentName = name; 510 } 511 512 public String getDisplayName(){ 513 return displayName; 514 } 515 516 public void setDisplayName(String name){ 517 displayName = name; 518 } 519 520 public void setClientAppServerSide(boolean clientAppServerSide) { 521 this.clientAppServerSide = clientAppServerSide; 522 } 523 524 public boolean isClientAppServerSide() { 525 return this.clientAppServerSide; 526 } 527 } 528 }