Package com.subhajit.eclipse.view.jar

Source Code of com.subhajit.eclipse.view.jar.GenerateDependenciesActionHandler

/**
*
*/
package com.subhajit.eclipse.view.jar;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.Map.Entry;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import com.subhajit.codeanalysis.files.LWRepository;
import com.subhajit.common.util.Graph;
import com.subhajit.common.util.IConstants;
import com.subhajit.common.util.IProgress;
import com.subhajit.common.util.Pair;
import com.subhajit.common.util.CommonUtils.IResource;
import com.subhajit.common.util.streams.FileUtils;
import com.subhajit.diagram.callgraph.CallGraphGeneratorUtils;
import com.subhajit.eclipse.util.ViewUtils;
import com.subhajit.eclipse.view.images.ImageView;
import com.subhajit.gui.progress.ISwingRunnableWithProgress;
import com.subhajit.gui.progress.TaskRunner;

final class GenerateDependenciesActionHandler implements ActionListener {
  /**
     *
     */
  private final JarPanel jarPanel;

  /**
   * @param jarPanel
   */
  GenerateDependenciesActionHandler(JarPanel jarPanel) {
    this.jarPanel = jarPanel;
  }

  public void actionPerformed(ActionEvent e) {
    if (this.jarPanel.repository == null) {
      return;
    }
    new Thread(new Runnable() {
      public void run() {
        final ConcurrentMap<File, Set<File>> filesMap = new ConcurrentHashMap<File, Set<File>>();
        final ConcurrentMap<File, Graph<String>> nodes = new ConcurrentHashMap<File, Graph<String>>();
        new TaskRunner(new ISwingRunnableWithProgress() {
          public void run(IProgress progress) throws Throwable {
            LWRepository repository = GenerateDependenciesActionHandler.this.jarPanel.repository;
            filesMap.putAll(updateFilesMap(repository, progress));

            progress.setRange(0, filesMap.entrySet().size());
            for (Map.Entry<File, Set<File>> entry : filesMap
                .entrySet()) {
              progress.increment(1, "");
              Graph<String> sourceNode = ensureNodeExists(nodes,
                  entry.getKey());
              for (File usedFile : entry.getValue()) {
                if (!usedFile.equals(entry.getKey())) {
                  Graph<String> targetNode = ensureNodeExists(
                      nodes, usedFile);
                  boolean alreadyParent = false;
                  for (Graph<String> child : sourceNode
                      .getChildren()) {
                    if (child == targetNode) {
                      alreadyParent = true;
                      break;
                    }
                  }
                  if (!alreadyParent) {
                    sourceNode.addChild(targetNode);
                  }
                }
              }
            }
          }
        }, "", "", 0).exec();
        new TaskRunner(new ISwingRunnableWithProgress() {
          public void run(IProgress progress) throws Throwable {
            progress.setRange(0, nodes.entrySet().size());
            File temporaryDir = new File(
                IConstants.JAVA_IO_TMPDIR_PATH + "/"
                    + UUID.randomUUID().toString());
            try {
              try {
                FileUtils.mkdirs(temporaryDir);
                for (Map.Entry<File, Graph<String>> entry : nodes
                    .entrySet()) {
                  progress.increment(1, "Processing "
                      + entry.getKey());
                  CallGraphGeneratorUtils
                      .draw(
                          entry.getValue(),
                          new File(
                              temporaryDir,
                              FileUtils
                                  .getFileNameSansExtension(entry
                                      .getKey()
                                      .getName())
                                  + ".png"));
                }
                File imageSaveFile = new File(
                    IConstants.JAVA_IO_TMPDIR_PATH + "/"
                        + "nodes.zip");
                FileUtils.createZipFile(temporaryDir,
                    imageSaveFile);
                // At this point, we wish to make this view
                // known to the image view. However, we may not
                // be running inside of eclipse, so we must be
                // careful to notify the image view only if we
                // are (running within eclipse).
                ViewUtils.showView(ImageView.VIEW_ID);
                ImageView.getInstance().getImageViewPanel()
                    .reInit(imageSaveFile);
              } finally {
                if (temporaryDir != null
                    && temporaryDir.exists()) {
                  FileUtils
                      .deleteDirectoryAndContents(temporaryDir);
                }
              }
            } catch (IOException exc) {
              exc.printStackTrace();
            } catch (InterruptedException exc) {
              Thread.currentThread().interrupt();
              return;
            }

            for (Map.Entry<File, Graph<String>> entry : nodes
                .entrySet()) {
              entry.getValue().clear();
            }
            nodes.clear();
          }
        }, "Computing nodes", "", 0).exec();
      }

      private Graph<String> ensureNodeExists(
          final ConcurrentMap<File, Graph<String>> nodes, File file) {
        Graph<String> node = nodes.get(file);
        if (node == null) {
          node = createNode(file);
          Graph<String> value = nodes.putIfAbsent(file, node);
          if (value != null) {
            node = value;
          }
        }
        return node;
      }
    }).start();
  }

  private final ConcurrentMap<File, Set<File>> updateFilesMap(
      final LWRepository repository, final IProgress progress) {
    final ConcurrentMap<String, File> classLocationMap = generateClassLocationMap(
        repository, progress);
    final ConcurrentMap<File, Set<File>> filesMap = new ConcurrentHashMap<File, Set<File>>();
    ExecutorService service = Executors.newFixedThreadPool(5);
    try {
      CompletionService<Set<File>> completionService = new ExecutorCompletionService<Set<File>>(
          service);
      int index = 0;
      final List<File> files = repository.getFiles();
      progress.setRange(0, files.size());
      for (final File file : files) {
        progress.increment(1, file.getName());
        Iterator<IResource> resourceIt = repository.getResources(file);
        while (resourceIt.hasNext()) {
          final IResource resource = resourceIt.next();
          if (resource.isDirectory()) {
            continue;
          }
          if (resource.getName().endsWith(".class")) {
            index++;
            completionService.submit(new Callable<Set<File>>() {
              public Set<File> call() throws Exception {
                final String className = resource.getName()
                    .substring(
                        0,
                        resource.getName().lastIndexOf(
                            ".class")).replace('/',
                        '.');
                Set<File> usedFiles = new HashSet<File>();
                for (String usedClass : repository.findClass(
                    className).getUsedClasses()) {
                  if ( classLocationMap == null ){
                    System.out.println("");
                  }
                  if ( usedClass == null ){
                    System.out.println("");
                  }
                  final File classLoadFile = classLocationMap
                      .get(usedClass);
                  if (classLoadFile != null) {
                    usedFiles.add(classLoadFile);
                  }
                }
                Set<File> files = filesMap.get(file);
                if (files == null) {
                  files = new HashSet<File>();
                  Set<File> value = filesMap.putIfAbsent(
                      file, files);
                  if (value != null) {
                    files = value;
                  }
                }
                synchronized (files) {
                  files.addAll(usedFiles);
                }
                return usedFiles;
              }
            });
          }
        }
      }
      int stepSize = index / 20;
      progress.setRange(0, 20);
      int value = 0;
      for (int i = 0; i < index; i++) {
        if (i != 0 && i % stepSize == 0) {
          progress.increment(1, value + "% completed");
          value += 5;
        }
        try {
          completionService.take().get();
        } catch (ExecutionException exc) {
          exc.getCause().printStackTrace();
        } catch (InterruptedException exc) {
          Thread.currentThread().interrupt();
          return null;
        }
      }
      return filesMap;
    } finally {
      service.shutdown();
    }
  }

  private ConcurrentMap<String, File> generateClassLocationMap(
      final LWRepository repository, final IProgress progress) {
    final ConcurrentMap<String, File> ret = new ConcurrentHashMap<String, File>();
    ExecutorService service = Executors.newFixedThreadPool(5);
    try {
      CompletionService<Map.Entry<String, File>> completionService = new ExecutorCompletionService<Map.Entry<String, File>>(
          service);
      int index = 0;
      int steps = 20;
      List<String> allDefinedClassNames = repository
          .getAllDefinedClassNames();
      int stepSize = allDefinedClassNames.size() / steps;
      progress.setRange(0, steps);
      for (final String className : allDefinedClassNames) {
        if (index % stepSize == 0) {
          progress.increment(1, "");
        }
        completionService
            .submit(new Callable<Map.Entry<String, File>>() {
              public Entry<String, File> call() throws Exception {
                final File file = repository
                    .locateClass(className);
                if (file == null) {
                  return null;
                } else {
                  return Pair.newInstance(className, file);
                }
              }
            });
        index++;
      }
      for (int i = 0; i < index; i++) {
        Map.Entry<String, File> entry;
        try {
          entry = completionService.take().get();
        } catch (InterruptedException e) {
          Thread.currentThread().interrupt();
          return null;
        } catch (ExecutionException e) {
          throw new UndeclaredThrowableException(e.getCause());
        }
        if (entry != null) {
          ret.put(entry.getKey(), entry.getValue());
        }
      }
      return ret;
    } finally {
      service.shutdown();
    }
  }

  /**
   * Create a {@link Graph} from the given <tt>file</tt>.
   *
   * @param file
   * @return
   */
  static Graph<String> createNode(File file) {
    return new Graph<String>(FileUtils.getFileNameSansExtension(file
        .getName()).replace('.', '_'));
  }
}
TOP

Related Classes of com.subhajit.eclipse.view.jar.GenerateDependenciesActionHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.