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