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.geronimo.console.classloaderview;
018    
019    import java.io.IOException;
020    import java.util.ArrayList;
021    import java.util.Iterator;
022    import java.util.Hashtable;
023    import java.util.List;
024    import java.util.Collections;
025    
026    import org.apache.geronimo.console.BasePortlet;
027    import org.apache.geronimo.console.util.StringTree;
028    
029    import javax.portlet.ActionRequest;
030    import javax.portlet.ActionResponse;
031    import javax.portlet.PortletConfig;
032    import javax.portlet.PortletException;
033    import javax.portlet.PortletRequestDispatcher;
034    import javax.portlet.RenderRequest;
035    import javax.portlet.RenderResponse;
036    import javax.portlet.WindowState;
037    
038    import org.apache.geronimo.kernel.util.ClassLoaderRegistry;
039    
040    public class ClassLoaderViewPortlet extends BasePortlet {
041    
042        private static final String NORMALVIEW_JSP = "/WEB-INF/view/classloaderview/view.jsp";
043    
044        private static final String MAXIMIZEDVIEW_JSP = "/WEB-INF/view/classloaderview/view.jsp";
045    
046        private static final String HELPVIEW_JSP = "/WEB-INF/view/classloaderview/help.jsp";
047    
048        private PortletRequestDispatcher normalView;
049    
050        private PortletRequestDispatcher maximizedView;
051    
052        private PortletRequestDispatcher helpView;
053        
054        private boolean inverse;
055    
056        public void processAction(ActionRequest actionRequest,
057                ActionResponse actionResponse) throws PortletException, IOException {
058            // set selectedNode
059            actionRequest.getPortletSession().setAttribute("selectedNode", actionRequest.getParameter("snNode"));
060            // toggle between inverse and non-inverse each time the form is processed
061            inverse = actionRequest.getParameter("inverse").equalsIgnoreCase("true")? true : false;
062            // toggle
063            inverse = (!inverse);
064            // store inverse variable for the jsp
065            actionRequest.getPortletSession().setAttribute("invert", inverse );
066        }
067    
068        protected void doView(RenderRequest renderRequest,
069                RenderResponse renderResponse) throws IOException, PortletException {
070            if (WindowState.MINIMIZED.equals(renderRequest.getWindowState())) {
071                return;
072            }
073            renderRequest.getPortletSession().setAttribute("classloaderTree", this);
074            renderRequest.setAttribute("inverse", inverse);
075            renderRequest.getPortletSession().setAttribute("inverse", inverse);
076    
077            if (WindowState.NORMAL.equals(renderRequest.getWindowState())) {
078                normalView.include(renderRequest, renderResponse);
079            } else {
080                maximizedView.include(renderRequest, renderResponse);
081            }
082        }
083    
084        protected void doHelp(RenderRequest renderRequest,
085                RenderResponse renderResponse) throws PortletException, IOException {
086            helpView.include(renderRequest, renderResponse);
087        }
088    
089        public void init(PortletConfig portletConfig) throws PortletException {
090            super.init(portletConfig);
091            normalView = portletConfig.getPortletContext().getRequestDispatcher(
092                    NORMALVIEW_JSP);
093            maximizedView = portletConfig.getPortletContext().getRequestDispatcher(
094                    MAXIMIZEDVIEW_JSP);
095            helpView = portletConfig.getPortletContext().getRequestDispatcher(
096                    HELPVIEW_JSP);
097            inverse = false;
098        }
099    
100        public void destroy() {
101            normalView = null;
102            maximizedView = null;
103            helpView = null;
104            super.destroy();
105        }
106    
107        public String getJSONTrees(boolean inverse) {
108            List list = getTrees(inverse);
109            if (list == null)
110                return "[]";
111    
112            StringBuffer stb = new StringBuffer();
113            stb.append("[");
114            Hashtable htLinks = new Hashtable();
115            // First level cannot be a link
116            for (int i = 0; i < list.size(); i++) {
117                StringTree node = (StringTree) list.get(i);
118                htLinks.put(node.name, ""+i);
119            }
120            for (int i = 0; i < list.size(); i++) {
121                StringTree node = (StringTree) list.get(i);
122                if (i != 0)
123                    stb.append(",");
124                stb.append(node.toJSONObject("" + i, htLinks, true));
125            }
126            stb.append("]");
127            list = null;
128            return stb.toString();
129        }
130    
131        public ArrayList getTrees(boolean inverse) {
132            ArrayList parentNodes = new ArrayList();
133            List list = ClassLoaderRegistry.getList();
134            Iterator iter = list.iterator();
135            while (iter.hasNext()) {
136                if(!inverse)
137                    updateTree((ClassLoader) iter.next(), parentNodes);
138                else
139                    inverseTree((ClassLoader) iter.next(), parentNodes);
140            }
141            Collections.sort(parentNodes);
142            return parentNodes;
143        }
144    
145        public StringTree inverseTree(ClassLoader classloader, ArrayList parentNodes) {
146            
147            StringTree node = new StringTree(classloader.toString());
148            int index = parentNodes.indexOf(node);
149            if(index != -1)
150                return (StringTree)parentNodes.get(index);
151            
152            node = addClasses(node, classloader);
153            
154            if (classloader instanceof org.apache.geronimo.kernel.config.MultiParentClassLoader) {
155                org.apache.geronimo.kernel.config.MultiParentClassLoader mpclassloader = (org.apache.geronimo.kernel.config.MultiParentClassLoader) classloader;
156                ClassLoader[] parents = mpclassloader.getParents();
157                if (parents != null)
158                    for (int i = 0; i < parents.length; i++) {
159                        StringTree parentNode = inverseTree(parents[i],parentNodes);
160                        node.addChild(parentNode);
161                    }
162            } else if (classloader.getParent() != null) {
163                StringTree parentNode = inverseTree(classloader.getParent(),parentNodes);
164                node.addChild(parentNode);
165            }        
166            if(!parentNodes.contains(node))
167                parentNodes.add(node);
168            
169            return node;
170        }
171    
172        public StringTree updateTree(ClassLoader classloader, ArrayList parentNodes) {
173    
174            Iterator iter = parentNodes.iterator();
175            StringTree node = null;
176            while (iter.hasNext()) {
177                StringTree currNode = (StringTree) iter.next();
178                node = currNode.findNode(classloader.toString());
179                if (node != null)
180                    return node;
181            }
182    
183            if (node == null) {
184                node = new StringTree(classloader.toString());
185                node = addClasses(node, classloader);
186    
187                if (classloader instanceof org.apache.geronimo.kernel.config.MultiParentClassLoader) {
188                    org.apache.geronimo.kernel.config.MultiParentClassLoader mpclassloader = (org.apache.geronimo.kernel.config.MultiParentClassLoader) classloader;
189                    ClassLoader[] parents = mpclassloader.getParents();
190                    if (parents == null)
191                        parentNodes.add(node);
192                    else if (parents.length == 0)
193                        parentNodes.add(node);
194                    else {
195                        for (int i = 0; i < parents.length; i++) {
196                            StringTree parentNode = updateTree(parents[i],
197                                    parentNodes);
198                            parentNode.addChild(node);
199                        }
200                    }
201                } else if (classloader.getParent() != null) {
202                    StringTree parentNode = updateTree(classloader.getParent(),
203                            parentNodes);
204                    parentNode.addChild(node);
205                } else
206                    parentNodes.add(node);
207            }
208            return node;
209        }
210    
211        private StringTree addClasses(StringTree node, ClassLoader loader) {
212            try {
213                java.lang.reflect.Field CLASSES_VECTOR_FIELD = ClassLoader.class
214                        .getDeclaredField("classes");
215    
216                if (CLASSES_VECTOR_FIELD.getType() != java.util.Vector.class) {
217                    return node;
218                }
219                CLASSES_VECTOR_FIELD.setAccessible(true);
220    
221                final java.util.Vector classes = (java.util.Vector) CLASSES_VECTOR_FIELD
222                        .get(loader);
223                if (classes == null)
224                    return node;
225    
226                final Class[] result;
227    
228                synchronized (classes) {
229                    result = new Class[classes.size()];
230                    classes.toArray(result);
231                }
232    
233                CLASSES_VECTOR_FIELD.setAccessible(false);
234    
235                StringTree classNames = new StringTree("Classes");
236                StringTree interfaceNames = new StringTree("Interfaces");
237                node.addChild(classNames);
238                node.addChild(interfaceNames);
239    
240                for (int i = 0; i < result.length; i++) {
241                    if (result[i].isInterface())
242                        interfaceNames.addChild(result[i].toString());
243                    else
244                        classNames.addChild(result[i].toString());
245                }
246    
247                return node;
248            } catch (Exception e) {
249                return node;
250            }
251        }
252    
253    }