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 }