Home » geronimo-2.2-source-release » org.apache.geronimo.console.classloaderview » [javadoc | source]

    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   package org.apache.geronimo.console.classloaderview;
   18   
   19   import java.util.ArrayList;
   20   import java.util.Collections;
   21   import java.util.Comparator;
   22   import java.util.HashMap;
   23   import java.util.Iterator;
   24   import java.util.List;
   25   import java.util.Map;
   26   
   27   import org.apache.geronimo.console.util.TreeEntry;
   28   import org.apache.geronimo.kernel.config.MultiParentClassLoader;
   29   import org.apache.geronimo.kernel.util.ClassLoaderRegistry;
   30   import org.directwebremoting.annotations.RemoteMethod;
   31   import org.directwebremoting.annotations.RemoteProxy;
   32   
   33   @RemoteProxy
   34   public class ClassLoaderViewHelper {
   35       Map<String, TreeEntry> nodeHash;
   36       private static final String NO_CHILD = "none";
   37       
   38       private static final String NORMAL_TYPE = "normal";
   39       
   40       private static final CmpTreeEntry cmp = new CmpTreeEntry();
   41   
   42       @RemoteMethod
   43       public String getTrees(boolean inverse) {
   44           nodeHash = new HashMap<String, TreeEntry>();
   45   
   46           List list = ClassLoaderRegistry.getList();
   47           Iterator iter = list.iterator();
   48           while (iter.hasNext()) {
   49               if (!inverse)
   50                   updateTree((ClassLoader) iter.next());
   51               else
   52                   inverseTree((ClassLoader) iter.next());
   53           }
   54   
   55           return this.printClassLoaders();
   56       }
   57   
   58       public TreeEntry inverseTree(ClassLoader classloader) {
   59           TreeEntry node = nodeHash.get(classloader.toString());
   60           if (null != node)
   61               return node;
   62           node = new TreeEntry(classloader.toString(), "root");
   63           node = addClasses(node, classloader);
   64           nodeHash.put(node.getName(), node);
   65   
   66           if (classloader instanceof MultiParentClassLoader) {
   67               MultiParentClassLoader mpclassloader = (MultiParentClassLoader) classloader;
   68               ClassLoader[] parents = mpclassloader.getParents();
   69               if (null != parents && 0 < parents.length) {
   70                   for (int i = 0; i < parents.length; i++) {
   71                       TreeEntry parentNode = inverseTree(parents[i]);
   72                       node.addChild(parentNode);
   73                   }
   74               }
   75           } else if (classloader.getParent() != null) {
   76               TreeEntry parentNode = inverseTree(classloader.getParent());
   77               node.addChild(parentNode);
   78           }
   79   
   80           return node;
   81       }
   82   
   83       public TreeEntry updateTree(ClassLoader classloader) {
   84   
   85           TreeEntry node = nodeHash.get(classloader.toString());
   86           if (null != node)
   87               return node;
   88   
   89           node = new TreeEntry(classloader.toString(), NORMAL_TYPE);
   90           node = addClasses(node, classloader);
   91           nodeHash.put(node.getName(), node);
   92   
   93           if (classloader instanceof MultiParentClassLoader) {
   94               MultiParentClassLoader mpclassloader = (MultiParentClassLoader) classloader;
   95               ClassLoader[] parents = mpclassloader.getParents();
   96               if (null != parents && 0 < parents.length) {
   97                   for (int i = 0; i < parents.length; i++) {
   98                       TreeEntry parentNode = updateTree(parents[i]);
   99                       parentNode.addChild(node);
  100                   }
  101               }
  102           } else if (classloader.getParent() != null) {
  103               TreeEntry parentNode = updateTree(classloader.getParent());
  104               parentNode.addChild(node);
  105           } else {
  106               node.setType("root");
  107           }
  108   
  109           return node;
  110       }
  111   
  112       private TreeEntry addClasses(TreeEntry node, ClassLoader loader) {
  113           try {
  114               java.lang.reflect.Field CLASSES_VECTOR_FIELD = ClassLoader.class.getDeclaredField("classes");
  115   
  116               if (CLASSES_VECTOR_FIELD.getType() != java.util.Vector.class) {
  117                   return node;
  118               }
  119               CLASSES_VECTOR_FIELD.setAccessible(true);
  120   
  121               final java.util.Vector classes = (java.util.Vector) CLASSES_VECTOR_FIELD.get(loader);
  122               if (classes == null)
  123                   return node;
  124   
  125               final Class[] result;
  126   
  127               synchronized (classes) {
  128                   result = new Class[classes.size()];
  129                   classes.toArray(result);
  130               }
  131   
  132               CLASSES_VECTOR_FIELD.setAccessible(false);
  133   
  134               TreeEntry classNames = new TreeEntry("Classes", NORMAL_TYPE);
  135               TreeEntry interfaceNames = new TreeEntry("Interfaces", NORMAL_TYPE);
  136               node.addChild(classNames);
  137               node.addChild(interfaceNames);
  138   
  139               for (int i = 0; i < result.length; i++) {
  140                   if (result[i].isInterface())
  141                       interfaceNames.addChild(new TreeEntry(result[i].toString(), NORMAL_TYPE));
  142                   else
  143                       classNames.addChild(new TreeEntry(result[i].toString(), NORMAL_TYPE));
  144               }
  145               if (classNames.getChildren().size() < 1)
  146                   classNames.addChild(new TreeEntry(NO_CHILD, NORMAL_TYPE));
  147               if (interfaceNames.getChildren().size() < 1)
  148                   interfaceNames.addChild(new TreeEntry(NO_CHILD, NORMAL_TYPE));
  149               return node;
  150           } catch (Exception e) {
  151               return node;
  152           }
  153       }
  154   
  155       /*
  156        * Usually we can directly give the java objects to clients via dwr, but we found that it is too slow when the
  157        * objects become larger and more complex because of the bad efficiency of dwr. So we need to translate the java
  158        * object to json text by hand in such cases. But it is more specific to the implementation of dojo, so it is not
  159        * very recommended.
  160        */
  161       String printClassLoaders() {
  162           // generate an ordered id
  163           List<TreeEntry> rootNodes = new ArrayList<TreeEntry>();
  164           for (TreeEntry entry : nodeHash.values()) {
  165               if (entry.getType().equals("root"))
  166                   rootNodes.add(entry);
  167           }
  168           markupId(-1, rootNodes); // here root nodes have already been sorted
  169   
  170           List<TreeEntry> allNodes = rootNodes;
  171           for (TreeEntry entry : nodeHash.values()) {
  172               if (!entry.getType().equals("root"))
  173                   allNodes.add(entry);
  174           }
  175           StringBuilder sb = new StringBuilder(512);
  176   
  177           sb.append("{label:\"name\",identifier:\"id\",items:[");
  178           Iterator<TreeEntry> list = allNodes.iterator();
  179           while (list.hasNext()) {
  180               TreeEntry curr = list.next();
  181               sb.append("{name:\"").append(curr.getName())
  182               .append("\",id:\"").append(curr.getId())
  183               .append("\",type:\"").append(curr.getType())
  184               .append("\",children:[");
  185   
  186               Iterator<TreeEntry> children = curr.getChildren().iterator();
  187               // the first child is Classes and the second one is Interfaces
  188               printClasses(sb, children.next());
  189               sb.append(",");
  190               printClasses(sb, children.next());
  191               while (children.hasNext()) {
  192                   TreeEntry child = children.next();
  193                   sb.append(",{_reference:\"").append(child.getId()).append("\"}");
  194               }
  195               if (list.hasNext())
  196                   sb.append("]},");
  197               else
  198                   sb.append("]}");
  199           }
  200           sb.append("]}");
  201           return sb.toString();
  202       }
  203   
  204       private void printClasses(StringBuilder sb, TreeEntry classes) {
  205           sb.append("{name:\"").append(classes.getName())
  206           .append("\",id:\"").append(classes.getId())
  207           .append("\",children:[");
  208           Iterator<TreeEntry> children = classes.getChildren().iterator();
  209           while (children.hasNext()) {
  210               TreeEntry child = children.next();
  211               sb.append("{name:\"").append(child.getName())
  212               .append("\",id:\"").append(child.getId())
  213               .append("\"}");
  214               if (children.hasNext())
  215                   sb.append(",");
  216           }
  217           sb.append("]}");
  218       }
  219   
  220       private int markupId(int pre, List<TreeEntry> list) {
  221           Collections.sort(list, cmp);
  222           for (TreeEntry child : list) {
  223               if (null == child.getId())
  224                   child.setId(String.valueOf(++pre));
  225               pre = markupId(pre, child.getChildren());
  226           }
  227           return pre;
  228       }
  229   
  230       static class CmpTreeEntry implements Comparator<TreeEntry> {
  231           public int compare(TreeEntry x, TreeEntry y) {
  232               if (x.getName() == null)
  233                   return -1;
  234               return x.getName().compareTo(y.getName());
  235           }
  236       }
  237   }

Home » geronimo-2.2-source-release » org.apache.geronimo.console.classloaderview » [javadoc | source]