All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gw.lang.init.ClasspathToGosuPathEntryUtil Maven / Gradle / Ivy

There is a newer version: 1.18.2
Show newest version
/*
 * Copyright 2014 Guidewire Software, Inc.
 */

package gw.lang.init;

import gw.config.CommonServices;
import gw.fs.IDirectory;
import gw.fs.IFile;
import gw.lang.GosuShop;
import gw.lang.UnstableAPI;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@UnstableAPI
public class ClasspathToGosuPathEntryUtil {
  static final String GW_FORBID_GOSU_JARS = "gw.forbid.gosu.jars";

  /**
   * Converts a set of Files into a list of GosuPathEntries.  The algorithm is as follows.  For each File in the list,
   * if that file is a directory or a jar file, see if there's a module.xml file in the root.  If so, parse that file
   * and add in a GosuPathEntry based on the module definition.  If not, if the file is a directory, look for
   * a module.xml file in the parent directory.  If such a file exists, add in a GosuPathEntry based on that file.
   * If no module.xml file has been found in either case, add a GosuPath entry for the directory or jar file using
   * the directory or jar as the root and as the only source directory, and with an empty list of custom typeloaders.
   * If the file is not a directory and not a jar file, ignore it entirely.
   *
   * In all cases, duplicate entries are ignored; if a GosuPathEntry is created previously for a File and the root
   * directory for that previous path entry is equal to or an ancestor of the root directory of the new path entry,
   * the new path entry is not added to the list.
   *
   * @param classpath the list of Files to turn into GosuPathEntries
   * @return an ordered list of GosuPathEntries created based on the algorithm described above
   */
  public static List convertClasspathToGosuPathEntries(List classpath) {
    // this is a hack to prevent loading of gosu directly from jar files in Diamond,
    // which prevents people from just embedding it in src and thus possibly having ND problems
    // it can be removed once "modules" are figured out in Emerald
    boolean loadingGosuFromJarsForbidden = Boolean.getBoolean(GW_FORBID_GOSU_JARS);
    ClassPathToGosuPathConverterBlock pathConverterBlock = new ClassPathToGosuPathConverterBlock();
    for ( IDirectory dir : classpath) {
      if (!dir.getName().endsWith(".jar") || !loadingGosuFromJarsForbidden) {
        executeOnSourceDirectory(dir, pathConverterBlock);
      } else {
        // Ignore anything that's not a directory or jar file
      }      
    }
    return (List) pathConverterBlock.getPathEntries();
  }

  public static IDirectory findModuleRootFromSourceEntry(IDirectory dir){
    ModuleFindFromSourceEntryBlock block = new ModuleFindFromSourceEntryBlock();
    executeOnSourceDirectory(dir, block);
    return block.getModuleDir();
  }

  private static IDirectory executeOnSourceDirectory(IDirectory dir, SourceDirectoryBlock block){
    IFile moduleFile = dir.file("pom.xml");
    IDirectory foundModule = null;
      if (moduleFile != null && moduleFile.exists()) {
        // This entry is itself a module, so return that
        block.doIt(dir, moduleFile);
      } else if (!dir.getName().endsWith(".jar")) {
        IDirectory parentDir = dir.getParent();
        if (parentDir != null) {
          IFile parentModuleFile = parentDir.file("pom.xml");
          if (parentModuleFile.exists() && moduleContainsSourceDir(parentModuleFile, dir)) {
            // Module.xml file in the parent directory, so that directory is a module
            block.doIt(parentDir, parentModuleFile);
          } else {
            // No module.xml file in the parent directory either, the original directory is the module
            block.doIt(dir, null);
          }
        } else {
          // No parent directory at all, so just the original directory is the module
          block.doIt(dir, null);
        }
      } else {
        // It's a jar file with no module.xml inside, so the jar is the module
        block.doIt(dir, null);
      }
    return foundModule;
  }

  private static boolean moduleContainsSourceDir(IFile moduleFile, IDirectory dir) {
    for (IDirectory iDirectory : ModuleFileUtil.createPathEntryForModuleFile(moduleFile).getSources()) {
      if(iDirectory.equals(dir)){
        return true;
      }
    }
    return false;
  }

  private interface SourceDirectoryBlock {
    void doIt(IDirectory dir, IFile moduleFile);
  }

  private static class ModuleFindFromSourceEntryBlock implements SourceDirectoryBlock {
    public IDirectory _moduleDir;

    @Override
    public void doIt(IDirectory dir, IFile moduleFile) {
      _moduleDir = dir;
    }

    public IDirectory getModuleDir(){
      return _moduleDir;
    }
  }

  private static class ClassPathToGosuPathConverterBlock implements SourceDirectoryBlock {
    private final List _pathEntries;

    public ClassPathToGosuPathConverterBlock() {
      _pathEntries = new ArrayList();
    }

    @Override
    public void doIt(IDirectory dir, IFile moduleFile) {
      if (!moduleAlreadyIncluded(dir, _pathEntries)) {
        if (moduleFile == null) {
          _pathEntries.add(new GosuPathEntry(dir, Collections.singletonList(dir)));
        } else {
          _pathEntries.add(GosuShop.createPathEntryFromModuleFile(moduleFile));
        }
      }
    }

    public List getPathEntries() {
      return _pathEntries;
    }

    private boolean moduleAlreadyIncluded(IDirectory rootDir, List pathEntries) {
      for (GosuPathEntry entry : pathEntries) {
        if (rootDir.equals(entry.getRoot()) || rootDir.isDescendantOf(entry.getRoot())) {
          return true;
        }
      }

      return false;
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy