Package erjang

Source Code of erjang.EModuleLoader

/** -*- tab-width: 4 -*-
* This file is part of Erjang - A JVM-based Erlang VM
*
* Copyright (c) 2010 by Trifork
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/

package erjang;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import kilim.Pausable;
import erjang.beam.BeamFileData;
import erjang.beam.BeamLoader;
import erjang.beam.EUtil;
import erjang.beam.loader.ErjangBeamDisLoader;
import erjang.driver.efile.ClassPathResource;
import erjang.util.Progress;

/** Handles the part of module loading that involves going from module name,
*  or module name plus beam file name, to a BeamFileData representation;
*  and chooses how to convert that into an EModule instance.
*  The EModule instance may be compiled, interpreted, or whatever.
*
*  The entire procedure looks roughly like this:
*  - File resolution: from module name to beam file name.
*  - File reading: from beam file name to raw beam data.
*  - Beam parsing: From raw beam data to beam representation (BeamFileData).
*  - Module creation: From beam representation to executable module (EModule).
*/
public class EModuleLoader {
  static final Logger log = Logger.getLogger("erjang.module.load");

  final static BeamLoader beamParser = new ErjangBeamDisLoader();

  /*==================== API ====================*/

  public static EModule find_and_load_module(String moduleName) throws IOException {
    File input = findBeamFile(moduleName);
    if (input == null)
      throw new FileNotFoundException(moduleName); // Is this the right error message?
    return load_module(moduleName, EUtil.readFile(input));
  }


  static long acc_int_load = 0;
  static long acc_load = 0;
   
  public static EModule load_module(String moduleName, EBinary beamBin) throws IOException {
    // This is where the module creation mode is selected.
    boolean use_interpreter = ErjangConfig.getBoolean("erjang.beam.option.i");
    long before = System.currentTimeMillis();
    long after;

    EModule loaded_module;
    Progress.activity("loading "+moduleName+"...");
    if (use_interpreter || moduleName.startsWith("elixir_compiler_")) {
      BeamFileData bfd = beamParser.load(beamBin.toByteArray());
      loaded_module = erjang.beam.interpreter.Interpreter.beamFileToEModule(bfd);
      after = System.currentTimeMillis();
    } else { // Use compiler
            EModuleClassLoader moduleClassLoader;
            try {
                 moduleClassLoader = ErjangCodeCache.getModuleClassLoader(moduleName, beamBin, beamParser);
            } catch (RuntimeException e) {
                moduleClassLoader = null;
            }

            if (moduleClassLoader != null) {
                after = System.currentTimeMillis();
                loaded_module = load_compiled_module(moduleName, moduleClassLoader);
            } else {
                log.warning("Compiling "+moduleName+" failed - falling back to interpreter");
                BeamFileData bfd = beamParser.load(beamBin.toByteArray());
                loaded_module = erjang.beam.interpreter.Interpreter.beamFileToEModule(bfd);
                after = System.currentTimeMillis();
            }
        }
    if (log.isLoggable(Level.FINE)) {
      long after_load = System.currentTimeMillis();
      if (use_interpreter)
        acc_int_load += (after_load-after);
      else
        acc_load += (after_load-after);
      log.fine("["
          + moduleName
          + ":"
          + ""+(after-before)+"ms"
          + ";"+(after_load-after)+"ms]"
          + "("+acc_load+")");
     }
    Progress.done();

    return loaded_module;
  }

  /*==================== BEAM FILE RESOLUTION STEP ====================*/

  private static File findBeamFile(String module) {
    String n = module;

    for (File e : loadPath) {
      File beam = new File(e, n + ".beam");
      if (beam.exists())
        return beam;
      if (ClassPathResource.read_file(beam.getPath()) != null)
        return beam;
    }

    return null;
  }

  final static List<File> loadPath = new ArrayList<File>();

  static {
    String sys_path = System.getenv("ERJ_PATH");
    if (sys_path != null)
      addLoadPaths(loadPath, sys_path);

    String path = ErjangConfig.getString("erjang.path", ".");
    addLoadPaths(loadPath, path);
  }

  private static void addLoadPaths(List<File> out, String path) {
    for (String s : path.split(File.pathSeparator)) {
      File elem = ERT.newFile(s);
      if (elem.exists() && elem.isDirectory()) {
        out.add(elem);
      }
    }
  }

  /*==================== MODULE CREATION STEP ====================*/

  @SuppressWarnings("unchecked")
  public static EModule load_compiled_module(String mod, EModuleClassLoader loader) {

    if (log.isLoggable(Level.FINE)) {
       log.fine("EML| load_compiled_module: "+mod+" @ "+loader);
    }
   
    String internalName = erjang.beam.Compiler.moduleClassName(mod);
    String java_name = internalName.replace('/', '.');
    Class<? extends EModule> clazz;
    try {
      clazz = (Class<? extends EModule>) loader.loadClass(java_name);
    } catch (ClassNotFoundException e1) {
      e1.printStackTrace();
      throw new ErlangError(e1);
    }
    EModule mi;
    try {
      mi = clazz.newInstance();
    } catch (Exception e) {
      e.printStackTrace();
      throw new ErlangError(e);
    }

    return mi;
  }

  public static EObject call_on_load_function(EProc proc, EAtom modName) throws Pausable {
    EModule mod = EModuleManager.get_loaded_module(modName);
    if (mod == null) {
      throw ERT.badarg(modName);
    }

    return mod.on_load(proc);
  }
}
TOP

Related Classes of erjang.EModuleLoader

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.