Package us.deathmarine.luyten

Source Code of us.deathmarine.luyten.Model$State

package us.deathmarine.luyten;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.Theme;
import org.fife.ui.rtextarea.RTextScrollPane;
import com.strobel.assembler.InputTypeLoader;
import com.strobel.assembler.metadata.ITypeLoader;
import com.strobel.assembler.metadata.JarTypeLoader;
import com.strobel.assembler.metadata.MetadataSystem;
import com.strobel.assembler.metadata.TypeDefinition;
import com.strobel.assembler.metadata.TypeReference;
import com.strobel.core.StringUtilities;
import com.strobel.core.VerifyArgument;
import com.strobel.decompiler.DecompilationOptions;
import com.strobel.decompiler.DecompilerSettings;
import com.strobel.decompiler.PlainTextOutput;

/**
* Jar-level model
*/
public class Model extends JSplitPane {
  private static final long serialVersionUID = 6896857630400910200L;

  private static final long MAX_JAR_FILE_SIZE_BYTES = 1_000_000_000;
  private static final long MAX_UNPACKED_FILE_SIZE_BYTES = 1_000_000;

    private static LuytenTypeLoader typeLoader = new LuytenTypeLoader();
    public static MetadataSystem metadataSystem = new MetadataSystem(typeLoader);

  private JTree tree;
  private JTabbedPane house;
  private File file;
  private DecompilerSettings settings;
  private DecompilationOptions decompilationOptions;
  private Theme theme;
  private MainWindow mainWindow;
  private JProgressBar bar;
  private JLabel label;
  private HashSet<OpenFile> hmap = new HashSet<OpenFile>();
  private Set<String> treeExpansionState;
  private boolean open = false;
  private State state;
  private ConfigSaver configSaver;
  private LuytenPreferences luytenPrefs;

  public Model(MainWindow mainWindow) {
    this.mainWindow = mainWindow;
    this.bar = mainWindow.getBar();
    this.label = mainWindow.getLabel();

    configSaver = ConfigSaver.getLoadedInstance();
    settings = configSaver.getDecompilerSettings();
    luytenPrefs = configSaver.getLuytenPreferences();

    try {
      String themeXml = luytenPrefs.getThemeXml();
      theme = Theme.load(getClass().getResourceAsStream(LuytenPreferences.THEME_XML_PATH + themeXml));
    } catch (Exception e1) {
      try {
        e1.printStackTrace();
        String themeXml = LuytenPreferences.DEFAULT_THEME_XML;
        luytenPrefs.setThemeXml(themeXml);
        theme = Theme.load(getClass().getResourceAsStream(LuytenPreferences.THEME_XML_PATH + themeXml));
      } catch (Exception e2) {
        e2.printStackTrace();
      }
    }

    tree = new JTree();
    tree.setModel(new DefaultTreeModel(null));
    tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
    tree.setCellRenderer(new CellRenderer());
    TreeListener tl = new TreeListener();
    tree.addMouseListener(tl);

    JPanel panel2 = new JPanel();
    panel2.setLayout(new BoxLayout(panel2, 1));
    panel2.setBorder(BorderFactory.createTitledBorder("Structure"));
    panel2.add(new JScrollPane(tree));

    house = new JTabbedPane();
    house.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
    house.addChangeListener(new TabChangeListener());

    JPanel panel = new JPanel();
    panel.setLayout(new BoxLayout(panel, 1));
    panel.setBorder(BorderFactory.createTitledBorder("Code"));
    panel.add(house);
    this.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
    this.setDividerLocation(250 % mainWindow.getWidth());
    this.setLeftComponent(panel2);
    this.setRightComponent(panel);

    decompilationOptions = new DecompilationOptions();
    decompilationOptions.setSettings(settings);
    decompilationOptions.setFullDecompilation(true);
  }

  public void showLegal(String legalStr) {
    OpenFile open = new OpenFile("Legal", "*/Legal", legalStr, theme);
    hmap.add(open);
    addOrSwitchToTab(open);
  }

  private void addOrSwitchToTab(OpenFile open) {
    String title = open.name;
    RTextScrollPane rTextScrollPane = open.scrollPane;
    if (house.indexOfTab(title) < 0) {
      house.addTab(title, rTextScrollPane);
      house.setSelectedIndex(house.indexOfTab(title));
      int index = house.indexOfTab(title);
      Tab ct = new Tab(title);
      ct.getButton().addMouseListener(new CloseTab(title));
      house.setTabComponentAt(index, ct);
    } else {
      house.setSelectedIndex(house.indexOfTab(title));
    }
  }

  private void closeOpenTab(int index) {
    RTextScrollPane co = (RTextScrollPane) house.getComponentAt(index);
    RSyntaxTextArea pane = (RSyntaxTextArea) co.getViewport().getView();
    OpenFile open = null;
    for (OpenFile file : hmap)
      if (pane.equals(file.textArea))
        open = file;
    if (open != null && hmap.contains(open))
      hmap.remove(open);
    house.remove(co);
  }

  private String getName(String path) {
    if (path == null)
      return "";
    int i = path.lastIndexOf("/");
    if (i == -1)
      i = path.lastIndexOf("\\");
    if (i != -1)
      return path.substring(i + 1);
    return path;
  }

  private class TreeListener extends MouseAdapter {
    @Override
    public void mousePressed(MouseEvent event) {
      boolean isClickCountMatches = (event.getClickCount() == 1 && luytenPrefs.isSingleClickOpenEnabled())
          || (event.getClickCount() == 2 && !luytenPrefs.isSingleClickOpenEnabled());
      if (!isClickCountMatches)
        return;

      if (!SwingUtilities.isLeftMouseButton(event))
        return;

      final TreePath trp = tree.getPathForLocation(event.getX(), event.getY());
      if (trp == null)
        return;

      Object lastPathComponent = trp.getLastPathComponent();
      boolean isLeaf = (lastPathComponent instanceof TreeNode && ((TreeNode) lastPathComponent).isLeaf());
      if (!isLeaf)
        return;

      new Thread() {
        public void run() {
          openEntryByTreePath(trp);
        }
      }.start();
    }
  }

  private void openEntryByTreePath(TreePath trp) {
    String name = "";
    String path = "";
    try {
      bar.setVisible(true);
      if (trp.getPathCount() > 1) {
        for (int i = 1; i < trp.getPathCount(); i++) {
          DefaultMutableTreeNode node = (DefaultMutableTreeNode) trp.getPathComponent(i);
          TreeNodeUserObject userObject = (TreeNodeUserObject) node.getUserObject();
          if (i == trp.getPathCount() - 1) {
            name = userObject.getOriginalName();
          } else {
            path = path + userObject.getOriginalName() + "/";
          }
        }
        path = path + name;

        if (file.getName().endsWith(".jar") || file.getName().endsWith(".zip")) {
          if (state == null) {
            JarFile jfile = new JarFile(file);
            ITypeLoader jarLoader = new JarTypeLoader(jfile);

            typeLoader.getTypeLoaders().add(jarLoader);
            state = new State(file.getCanonicalPath(), file, jfile, jarLoader);
          }

          JarEntry entry = state.jarFile.getJarEntry(path);
          if (entry == null) {
            throw new FileEntryNotFoundException();
          }
          if (entry.getSize() > MAX_UNPACKED_FILE_SIZE_BYTES) {
            throw new TooLargeFileException(entry.getSize());
          }
          String entryName = entry.getName();
          if (entryName.endsWith(".class")) {
            label.setText("Extracting: " + name);
            String internalName = StringUtilities.removeRight(entryName, ".class");
            TypeReference type = metadataSystem.lookupType(internalName);
            extractClassToTextPane(type, name, path);
          } else {
            label.setText("Opening: " + name);
            try (InputStream in = state.jarFile.getInputStream(entry);) {
              extractSimpleFileEntryToTextPane(in, name, path);
            }
          }
        }
      } else {
        name = file.getName();
        path = file.getPath().replaceAll("\\\\", "/");
        if (file.length() > MAX_UNPACKED_FILE_SIZE_BYTES) {
          throw new TooLargeFileException(file.length());
        }
        if (name.endsWith(".class")) {
          label.setText("Extracting: " + name);
          TypeReference type = metadataSystem.lookupType(path);
          extractClassToTextPane(type, name, path);
        } else {
          label.setText("Opening: " + name);
          try (InputStream in = new FileInputStream(file);) {
            extractSimpleFileEntryToTextPane(in, name, path);
          }
        }
      }
      label.setText("Complete");
    } catch (FileEntryNotFoundException e) {
      label.setText("File not found: " + name);
    } catch (FileIsBinaryException e) {
      label.setText("Binary resource: " + name);
    } catch (TooLargeFileException e) {
      label.setText("File is too large: " + name + " - size: " + e.getReadableFileSize());
    } catch (Exception e) {
      label.setText("Cannot open: " + name);
      e.printStackTrace();
      JOptionPane.showMessageDialog(null, e.toString(), "Error!", JOptionPane.ERROR_MESSAGE);
    } finally {
      bar.setVisible(false);
    }
  }

  private void extractClassToTextPane(TypeReference type, String tabTitle, String path) throws Exception {
    if (tabTitle == null || tabTitle.trim().length() < 1 || path == null) {
      throw new FileEntryNotFoundException();
    }
    OpenFile sameTitledOpen = null;
    for (OpenFile nextOpen : hmap) {
      if (tabTitle.equals(nextOpen.name)) {
        sameTitledOpen = nextOpen;
        break;
      }
    }
    if (sameTitledOpen != null && path.equals(sameTitledOpen.getPath()) &&
        type.equals(sameTitledOpen.getType()) && sameTitledOpen.isContentValid()) {
      addOrSwitchToTab(sameTitledOpen);
      return;
    }

    // build tab content: do decompilation
    String decompiledSource = extractClassToString(type);

    // open tab, store type information
    if (sameTitledOpen != null) {
      sameTitledOpen.setContent(decompiledSource);
      sameTitledOpen.setPath(path);
      sameTitledOpen.setType(type);
      sameTitledOpen.setContentValid(true);
      addOrSwitchToTab(sameTitledOpen);
    } else {
      OpenFile open = new OpenFile(type, tabTitle, path, decompiledSource, theme);
      open.setContentValid(true);
      hmap.add(open);
      addOrSwitchToTab(open);
    }
  }

  private String extractClassToString(TypeReference type) throws Exception {
    // synchronized: do not accept changes from menu while running
    synchronized (settings) {
      TypeDefinition resolvedType = null;
      if (type == null || ((resolvedType = type.resolve()) == null)) {
        throw new Exception("Unable to resolve type.");
      }
      StringWriter stringwriter = new StringWriter();
      settings.getLanguage().decompileType(resolvedType,
          new PlainTextOutput(stringwriter), decompilationOptions);
      return stringwriter.toString();
    }
  }

  private void extractSimpleFileEntryToTextPane(InputStream inputStream, String tabTitle, String path)
      throws Exception {
    if (inputStream == null || tabTitle == null || tabTitle.trim().length() < 1 || path == null) {
      throw new FileEntryNotFoundException();
    }
    OpenFile sameTitledOpen = null;
    for (OpenFile nextOpen : hmap) {
      if (tabTitle.equals(nextOpen.name)) {
        sameTitledOpen = nextOpen;
        break;
      }
    }
    if (sameTitledOpen != null && path.equals(sameTitledOpen.getPath())) {
      addOrSwitchToTab(sameTitledOpen);
      return;
    }

    // build tab content
    StringBuilder sb = new StringBuilder();
    long nonprintableCharactersCount = 0;
    try (InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
        BufferedReader reader = new BufferedReader(inputStreamReader);) {
      String line;
      while ((line = reader.readLine()) != null) {
        sb.append(line).append("\n");

        for (byte nextByte : line.getBytes()) {
          if (nextByte <= 0) {
            nonprintableCharactersCount++;
          }
        }

      }
    }

    // guess binary or text
    String extension = "." + tabTitle.replaceAll("^[^\\.]*$", "").replaceAll("[^\\.]*\\.", "");
    boolean isTextFile = (OpenFile.WELL_KNOWN_TEXT_FILE_EXTENSIONS.contains(extension) ||
        nonprintableCharactersCount < sb.length() / 5);
    if (!isTextFile) {
      throw new FileIsBinaryException();
    }

    // open tab
    if (sameTitledOpen != null) {
      sameTitledOpen.setContent(sb.toString());
      sameTitledOpen.setPath(path);
      addOrSwitchToTab(sameTitledOpen);
    } else {
      OpenFile open = new OpenFile(tabTitle, path, sb.toString(), theme);
      hmap.add(open);
      addOrSwitchToTab(open);
    }
  }

  private class TabChangeListener implements ChangeListener {
    @Override
    public void stateChanged(ChangeEvent e) {
      int selectedIndex = house.getSelectedIndex();
      if (selectedIndex < 0) {
        return;
      }
      for (OpenFile open : hmap) {
        if (house.indexOfTab(open.name) == selectedIndex) {

          if (open.getType() != null && !open.isContentValid()) {
            updateOpenClass(open);
            break;
          }

        }
      }
    }
  }

  public void updateOpenClasses() {
    // invalidate all open classes (update will hapen at tab change)
    for (OpenFile open : hmap) {
      open.setContentValid(false);
    }
    // ensure not showing old codes
    for (OpenFile open : hmap) {
      if (open.getType() != null) {
        open.setContent("");
      }
    }
    // update the current open tab - if it is a class
    for (OpenFile open : hmap) {
      if (open.getType() != null && isTabInForeground(open)) {
        updateOpenClass(open);
        break;
      }
    }
  }

  private void updateOpenClass(final OpenFile open) {
    if (open.getType() == null) {
      return;
    }
    new Thread(new Runnable() {
      @Override
      public void run() {
        try {
          bar.setVisible(true);
          label.setText("Extracting: " + open.name);
          String decompiledSource = extractClassToString(open.getType());
          open.setContent(decompiledSource);
          open.setContentValid(true);
          label.setText("Complete");
        } catch (Exception e) {
          label.setText("Error, cannot update: " + open.name);
        } finally {
          bar.setVisible(false);
        }
      }
    }).start();
  }

  private boolean isTabInForeground(OpenFile open) {
    String title = open.name;
    int selectedIndex = house.getSelectedIndex();
    return (selectedIndex >= 0 && selectedIndex == house.indexOfTab(title));
  }

  private final class State implements AutoCloseable {
    private final String key;
    private final File file;
    final JarFile jarFile;
    final ITypeLoader typeLoader;

    private State(String key, File file, JarFile jarFile, ITypeLoader typeLoader) {
      this.key = VerifyArgument.notNull(key, "key");
      this.file = VerifyArgument.notNull(file, "file");
      this.jarFile = jarFile;
      this.typeLoader = typeLoader;
    }

    @Override
    public void close() {
      if (typeLoader != null) {
        Model.this.typeLoader.getTypeLoaders().remove(typeLoader);
      }
      Closer.tryClose(jarFile);
    }

    @SuppressWarnings("unused")
    public File getFile() {
      return file;
    }

    @SuppressWarnings("unused")
    public String getKey() {
      return key;
    }
  }

  private class Tab extends JPanel {
    private static final long serialVersionUID = -514663009333644974L;
    private JLabel closeButton = new JLabel(new ImageIcon(Toolkit.getDefaultToolkit().getImage(
        this.getClass().getResource("/resources/icon_close.png"))));
    private JLabel tabTitle = new JLabel();
    private String title = "";

    public Tab(String t) {
      super(new GridBagLayout());
      this.setOpaque(false);

      this.title = t;
      this.tabTitle = new JLabel(title);

      this.createTab();
    }

    public JLabel getButton() {
      return this.closeButton;
    }

    public void createTab() {
      GridBagConstraints gbc = new GridBagConstraints();
      gbc.gridx = 0;
      gbc.gridy = 0;
      gbc.weightx = 1;
      this.add(tabTitle, gbc);
      gbc.gridx++;
      gbc.insets = new Insets(0, 5, 0, 0);
      gbc.anchor = GridBagConstraints.EAST;
      this.add(closeButton, gbc);
    }
  }

  private class CloseTab extends MouseAdapter {
    String title;

    public CloseTab(String title) {
      this.title = title;
    }

    @Override
    public void mouseClicked(MouseEvent e) {
      int index = house.indexOfTab(title);
      closeOpenTab(index);
    }
  }

  public DefaultMutableTreeNode loadNodesByNames(DefaultMutableTreeNode node, List<String> originalNames) {
    List<TreeNodeUserObject> args = new ArrayList<>();
    for (String originalName : originalNames) {
      args.add(new TreeNodeUserObject(originalName));
    }
    return loadNodesByUserObj(node, args);
  }

  public DefaultMutableTreeNode loadNodesByUserObj(DefaultMutableTreeNode node, List<TreeNodeUserObject> args) {
    if (args.size() > 0) {
      TreeNodeUserObject name = args.remove(0);
      DefaultMutableTreeNode nod = getChild(node, name);
      if (nod == null)
        nod = new DefaultMutableTreeNode(name);
      node.add(loadNodesByUserObj(nod, args));
    }
    return node;
  }

  @SuppressWarnings("unchecked")
  public DefaultMutableTreeNode getChild(DefaultMutableTreeNode node, TreeNodeUserObject name) {
    Enumeration<DefaultMutableTreeNode> entry = node.children();
    while (entry.hasMoreElements()) {
      DefaultMutableTreeNode nods = entry.nextElement();
      if (((TreeNodeUserObject) nods.getUserObject()).getOriginalName().equals(name.getOriginalName())) {
        return nods;
      }
    }
    return null;
  }

  public void loadFile(File file) {
    if (open)
      closeFile();
    this.file = file;
    loadTree();
  }

  public void updateTree() {
    TreeUtil treeUtil = new TreeUtil(tree);
    treeExpansionState = treeUtil.getExpansionState();
    loadTree();
  }

  public void loadTree() {
    new Thread(new Runnable() {
      @Override
      public void run() {
        try {
          if (file == null) {
            return;
          }
          tree.setModel(new DefaultTreeModel(null));

          if (file.length() > MAX_JAR_FILE_SIZE_BYTES) {
            throw new TooLargeFileException(file.length());
          }
          if (file.getName().endsWith(".zip") || file.getName().endsWith(".jar")) {
            JarFile jfile;
            jfile = new JarFile(file);
            label.setText("Loading: " + jfile.getName());
            bar.setVisible(true);

            JarEntryFilter jarEntryFilter = new JarEntryFilter(jfile);
            List<String> mass = null;
            if (luytenPrefs.isFilterOutInnerClassEntries()) {
              mass = jarEntryFilter.getEntriesWithoutInnerClasses();
            } else {
              mass = jarEntryFilter.getAllEntriesFromJar();
            }
            buildTreeFromMass(mass);

            if (state == null) {
              ITypeLoader jarLoader = new JarTypeLoader(jfile);
              typeLoader.getTypeLoaders().add(jarLoader);
              state = new State(file.getCanonicalPath(), file, jfile, jarLoader);
            }
            open = true;
            label.setText("Complete");
          } else {
            TreeNodeUserObject topNodeUserObject = new TreeNodeUserObject(getName(file.getName()));
            final DefaultMutableTreeNode top = new DefaultMutableTreeNode(topNodeUserObject);
            tree.setModel(new DefaultTreeModel(top));
            settings.setTypeLoader(new InputTypeLoader());
            open = true;
            label.setText("Complete");

            // open it automatically
            new Thread() {
              public void run() {
                TreePath trp = new TreePath(top.getPath());
                openEntryByTreePath(trp);
              };
            }.start();
          }

          if (treeExpansionState != null) {
            try {
              TreeUtil treeUtil = new TreeUtil(tree);
              treeUtil.restoreExpanstionState(treeExpansionState);
            } catch (Exception exc) {
              exc.printStackTrace();
            }
          }
        } catch (TooLargeFileException e) {
          label.setText("File is too large: " + file.getName() + " - size: " + e.getReadableFileSize());
          closeFile();
        } catch (Exception e1) {
          e1.printStackTrace();
          label.setText("Cannot open: " + file.getName());
          closeFile();
        } finally {
          mainWindow.onFileLoadEnded(file, open);
          bar.setVisible(false);
        }
      }

    }).start();
  }

  private void buildTreeFromMass(List<String> mass) {
    if (luytenPrefs.isPackageExplorerStyle()) {
      buildFlatTreeFromMass(mass);
    } else {
      buildDirectoryTreeFromMass(mass);
    }
  }

  private void buildDirectoryTreeFromMass(List<String> mass) {
    TreeNodeUserObject topNodeUserObject = new TreeNodeUserObject(getName(file.getName()));
    DefaultMutableTreeNode top = new DefaultMutableTreeNode(topNodeUserObject);
    List<String> sort = new ArrayList<String>();
    Collections.sort(mass, String.CASE_INSENSITIVE_ORDER);
    for (String m : mass)
      if (m.contains("META-INF") && !sort.contains(m))
        sort.add(m);
    Set<String> set = new HashSet<String>();
    for (String m : mass) {
      if (m.contains("/")) {
        set.add(m.substring(0, m.lastIndexOf("/") + 1));
      }
    }
    List<String> packs = Arrays.asList(set.toArray(new String[] {}));
    Collections.sort(packs, String.CASE_INSENSITIVE_ORDER);
    Collections.sort(packs, new Comparator<String>() {
      public int compare(String o1, String o2) {
        return o2.split("/").length - o1.split("/").length;
      }
    });
    for (String pack : packs)
      for (String m : mass)
        if (!m.contains("META-INF") && m.contains(pack)
            && !m.replace(pack, "").contains("/"))
          sort.add(m);
    for (String m : mass)
      if (!m.contains("META-INF") && !m.contains("/") && !sort.contains(m))
        sort.add(m);
    for (String pack : sort) {
      LinkedList<String> list = new LinkedList<String>(Arrays.asList(pack.split("/")));
      loadNodesByNames(top, list);
    }
    tree.setModel(new DefaultTreeModel(top));
  }

  private void buildFlatTreeFromMass(List<String> mass) {
    TreeNodeUserObject topNodeUserObject = new TreeNodeUserObject(getName(file.getName()));
    DefaultMutableTreeNode top = new DefaultMutableTreeNode(topNodeUserObject);

    TreeMap<String, TreeSet<String>> packages = new TreeMap<>();
    HashSet<String> classContainingPackageRoots = new HashSet<>();

    Comparator<String> sortByFileExtensionsComparator = new Comparator<String>() {
      // (assertion: mass does not contain null elements)
      @Override
      public int compare(String o1, String o2) {
        int comp = o1.replaceAll("[^\\.]*\\.", "").compareTo(o2.replaceAll("[^\\.]*\\.", ""));
        if (comp != 0)
          return comp;
        return o1.compareTo(o2);
      }
    };

    for (String entry : mass) {
      String packagePath = "";
      String packageRoot = "";
      if (entry.contains("/")) {
        packagePath = entry.replaceAll("/[^/]*$", "");
        packageRoot = entry.replaceAll("/.*$", "");
      }
      String packageEntry = entry.replace(packagePath + "/", "");
      if (!packages.containsKey(packagePath)) {
        packages.put(packagePath, new TreeSet<String>(sortByFileExtensionsComparator));
      }
      packages.get(packagePath).add(packageEntry);
      if (!entry.startsWith("META-INF") && packageRoot.trim().length() > 0 &&
          entry.matches(".*\\.(class|java|prop|properties)$")) {
        classContainingPackageRoots.add(packageRoot);
      }
    }

    // META-INF comes first -> not flat
    for (String packagePath : packages.keySet()) {
      if (packagePath.startsWith("META-INF")) {
        List<String> packagePathElements = Arrays.asList(packagePath.split("/"));
        for (String entry : packages.get(packagePath)) {
          ArrayList<String> list = new ArrayList<>(packagePathElements);
          list.add(entry);
          loadNodesByNames(top, list);
        }
      }
    }

    // real packages: path starts with a classContainingPackageRoot -> flat
    for (String packagePath : packages.keySet()) {
      String packageRoot = packagePath.replaceAll("/.*$", "");
      if (classContainingPackageRoots.contains(packageRoot)) {
        for (String entry : packages.get(packagePath)) {
          ArrayList<TreeNodeUserObject> list = new ArrayList<>();
          list.add(new TreeNodeUserObject(packagePath, packagePath.replaceAll("/", ".")));
          list.add(new TreeNodeUserObject(entry));
          loadNodesByUserObj(top, list);
        }
      }
    }

    // the rest, not real packages but directories -> not flat
    for (String packagePath : packages.keySet()) {
      String packageRoot = packagePath.replaceAll("/.*$", "");
      if (!classContainingPackageRoots.contains(packageRoot) &&
          !packagePath.startsWith("META-INF") && packagePath.length() > 0) {
        List<String> packagePathElements = Arrays.asList(packagePath.split("/"));
        for (String entry : packages.get(packagePath)) {
          ArrayList<String> list = new ArrayList<>(packagePathElements);
          list.add(entry);
          loadNodesByNames(top, list);
        }
      }
    }

    // the default package -> not flat
    String packagePath = "";
    if (packages.containsKey(packagePath)) {
      for (String entry : packages.get(packagePath)) {
        ArrayList<String> list = new ArrayList<>();
        list.add(entry);
        loadNodesByNames(top, list);
      }
    }
    tree.setModel(new DefaultTreeModel(top));
  }

  public void closeFile() {
    for (OpenFile co : hmap) {
      int pos = house.indexOfTab(co.name);
      if (pos >= 0)
        house.remove(pos);
    }

    final State oldState = state;
    Model.this.state = null;
    if (oldState != null) {
      Closer.tryClose(oldState);
    }

    hmap.clear();
    tree.setModel(new DefaultTreeModel(null));
    metadataSystem = new MetadataSystem(typeLoader);
    file = null;
    treeExpansionState = null;
    open = false;
    mainWindow.onFileLoadEnded(file, open);
  }

  public void changeTheme(String xml) {
    InputStream in = getClass().getResourceAsStream(LuytenPreferences.THEME_XML_PATH + xml);
    try {
      if (in != null) {
        theme = Theme.load(in);
        for (OpenFile f : hmap) {
          theme.apply(f.textArea);
        }
      }
    } catch (Exception e1) {
      e1.printStackTrace();
      JOptionPane.showMessageDialog(null, e1.toString(), "Error!", JOptionPane.ERROR_MESSAGE);
    }
  }

  public File getOpenedFile() {
    File openedFile = null;
    if (file != null && open) {
      openedFile = file;
    }
    if (openedFile == null) {
      label.setText("No open file");
    }
    return openedFile;
  }

  public String getCurrentTabTitle() {
    String tabTitle = null;
    try {
      int pos = house.getSelectedIndex();
      if (pos >= 0) {
        tabTitle = house.getTitleAt(pos);
      }
    } catch (Exception e1) {
      e1.printStackTrace();
    }
    if (tabTitle == null) {
      label.setText("No open tab");
    }
    return tabTitle;
  }

  public RSyntaxTextArea getCurrentTextArea() {
    RSyntaxTextArea currentTextArea = null;
    try {
      int pos = house.getSelectedIndex();
      if (pos >= 0) {
        RTextScrollPane co = (RTextScrollPane) house.getComponentAt(pos);
        currentTextArea = (RSyntaxTextArea) co.getViewport().getView();
      }
    } catch (Exception e1) {
      e1.printStackTrace();
    }
    if (currentTextArea == null) {
      label.setText("No open tab");
    }
    return currentTextArea;
  }

  public void startWarmUpThread() {
    new Thread() {
      public void run() {
        try {
          Thread.sleep(500);
          String internalName = FindBox.class.getName();
          TypeReference type = metadataSystem.lookupType(internalName);
          TypeDefinition resolvedType = null;
          if ((type == null) || ((resolvedType = type.resolve()) == null)) {
            return;
          }
          StringWriter stringwriter = new StringWriter();
          settings.getLanguage().decompileType(resolvedType,
              new PlainTextOutput(stringwriter), decompilationOptions);
          String decompiledSource = stringwriter.toString();
          OpenFile open = new OpenFile(internalName, "*/" + internalName, decompiledSource, theme);
          JTabbedPane pane = new JTabbedPane();
          pane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
          pane.addTab("title", open.scrollPane);
          pane.setSelectedIndex(pane.indexOfTab("title"));
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }.start();
  }
}
TOP

Related Classes of us.deathmarine.luyten.Model$State

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.