Package anvil.script

Source Code of anvil.script.ModuleEnvelope

/*
* $Id: ModuleEnvelope.java,v 1.2 2002/09/16 08:05:03 jkl Exp $
*
* Copyright (c) 2002 Njet Communications Ltd. All Rights Reserved.
*
* Use is subject to license terms, as defined in
* Anvil Sofware License, Version 1.1. See LICENSE
* file, or http://njet.org/license-1.1.txt
*/
package anvil.script;

import anvil.ErrorListener;
import anvil.ForgingException;
import anvil.parser.InputSource;
import anvil.server.Address;
import anvil.server.CompilerPreferences;
import anvil.server.LocalizationPreferences;
import anvil.server.Resource;
import anvil.server.Loader;
import anvil.server.ZoneClassLoader;
import anvil.script.compiler.CompiledModule;
import anvil.script.compiler.ByteCompiler;
import anvil.script.parser.ScriptParser;
import anvil.script.parser.TemplateParser;
import anvil.script.statements.ModuleStatement;
import java.io.File;
import java.io.InputStream;
import java.io.IOException;
import java.net.URL;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;

/**
* class ModuleEnvelope
*
* @author: Jani Lehtim�ki
*/
public class ModuleEnvelope
{

  protected ModuleCache     _cache;
  protected Address         _address;
  protected long            _lastModified;
  protected String          _descriptor;
  protected ModuleStatement _script1;
  protected CompiledModule  _script2;
  protected int             _version = 0;
  protected boolean         _initialized = false;


  public ModuleEnvelope(ModuleCache cache, Address address, InputSource source) throws IOException, ForgingException
  {
    this(cache, address, source, 0, false);
  }


  protected ModuleEnvelope(ModuleCache cache, Address address, InputSource source, int version, boolean forceParsing)
    throws IOException, ForgingException
  {
    _cache   = cache;
    _address = address;
    _version = version;
   
    CompilerPreferences  prefs = address.getZone().getCompilerPreferences();
    String path = anvil.Version.getBuild() + address.getPathinfo();
    String postfix = (version!=0) ? "/v_"+version : "";
    String descriptor = mangle(path);
    boolean usetimestamp = prefs.getUseTimestamp();
    if (!(usetimestamp && forceParsing)) {
      _lastModified = -1;
      _descriptor = descriptor + postfix;
      if (!forceParsing) {
        if (loadClass()) {
          return;
        }
      }
    }

    if (usetimestamp) {
      _lastModified = source.getLastModified();
      _descriptor = addTimestamp(descriptor, _lastModified) + postfix;
      if (!forceParsing) {
        if (loadClass()) {
          return;
        }
      }
    }

    parse(source);
  }

  public long getLastModified()
  {
    return _lastModified;
  }

 
  public Address getAddress()
  {
    return _address;
  }
 

  public String getClassname()
  {
    return _descriptor.replace('/', '.');
  }


  public String getDescriptor()
  {
    return _descriptor;
  }


  public int getVersion()
  {
    return _version;
  }


  public Module getModule()
  {
    Module script = _script2;
    if (script != null) {
      return script;
    }
    return _script1;
  }

 
  public boolean isCompiled()
  {
    return _script2 != null;
  }
 

  public void parse(InputSource source) throws IOException, ForgingException
  {
    URL url = source.getURL();
    int length = source.getLength();
    int pos = 0;
    byte[] content = new byte[(int)length];
    InputStream input = null;
   
    try {
      input = source.getInputStream();
      while(pos < length) {
        int read = input.read(content, pos, length - pos);
        if (read == 0) {
          throw new IOException("Unexcepted end of " + url + " at position "+pos);
        }
        pos += read;
      }
    } finally {
      try {
        input.close();
      } catch (Throwable t) {
      }
      try {
        source.close();
      } catch (Throwable t) {
      }
    }
   
    if (pos < length) {
      java.util.Arrays.fill(content, pos, length, (byte)' ');
    }

    boolean is_template = false;
    pos = 0;
    out:
    while(pos < length) {
      switch(content[pos++]) {
      case (byte)'<':
        is_template = true;
        break out;

      case (byte)' ':
      case (byte)'\t':
      case (byte)'\r':
      case (byte)'\n':
        break;

      default:
        break out;
      }
    }
    if (pos == length) {
      throw new IOException("File is empty: " + url);
    }
   
    if (is_template) {
      TemplateParser parser = new TemplateParser(this,
        _address.getZone().getNamespace(), url, content);
      _script1 = parser.parseTemplate();

    } else {
      ScriptParser parser = new ScriptParser(this, url, content);
      _script1 = parser.parseScript();
    }
   
    _address.getZone().log().info("parsed: " + _address);
  }



  public ModuleEnvelope forge() throws IOException, ForgingException
  {
    Resource resource = _address.openResource();
    return new ModuleEnvelope(_cache, _address, resource, _version+1, true);
  }


  public void importExternals(ErrorListener listener)
  {
    if (_script1 != null) {
      _script1.importExternals(listener);
    }
   
  }


  public void resolve(Resolver resolver)
  {
    if (_script1 != null) {
      resolver.resolveScope(_script1);
    }
  }
 

  public void verifyPassOne(Verifier verifier)
  {
    if (_script1 != null) {
      verifier.verifyScope(_script1);
    }
  }
 

  public void verifyPassTwo(Verifier verifier)
  {
    if (_script1 != null) {
      verifier.checkScope(_script1);
    }
  } 

  public void check(ErrorListener context)
  {
    if (_script1 != null) {
      _script1.check(context);
    }
  }
  public void compile(Smith smith)
  {
    if (_script1 != null) {
      ByteCompiler c = new ByteCompiler(smith, this);
      if (c.compile()) {
        _address.getZone().log().info("code generated: " + _descriptor);
      } else {
        _address.getZone().log().info("code generation failed: " + _descriptor);
      }
    }
  }


  public boolean loadClass()
  {
    if (_script2 != null) {
      return true;
    }
    CompiledModule script = doLoadClass();
    if (script != null) {
      _script1 = null;
      _script2 = script;
      return true;
    } else {
      return false;
    }
  }
 
  private CompiledModule doLoadClass()
  {
    String classname = getClassname();
    try {
      ZoneClassLoader clsldr = _address.getZone().getClassLoader();
      Class cls = clsldr.loadClass(classname);
      CompiledModule script = (CompiledModule)cls.newInstance();
      classname   = cls.getName();
      _descriptor = classname.replace('.', '/');
      _version    = script.getVersion();
      script.init(_address);
      _address.getZone().log().info("code loaded: " + classname + ", version "+_version);
      return script;
    } catch (NoClassDefFoundError exception) {
      //ignore
    } catch (ClassNotFoundException exception) {
      //ignore
    } catch (InstantiationException exception) {
      _address.getZone().log().error("Error when loading '"+classname+"'", exception);
    } catch (IllegalAccessException exception) {
      _address.getZone().log().error("Error when loading '"+classname+"'", exception);
    } catch (LinkageError error) {
      _address.getZone().log().error("Error when loading '"+classname+"'", error);
    }
    return null;
  }
 

  public void init(ErrorListener listener)
  {
    synchronized(this) {
      if (_initialized) {
        return;
      }
      _initialized = true;
    }
    CompiledModule script = _script2;
    if (script != null) {
      Context context = new Context(_address.getZone());
      context.push(script, null, 0, 0, false);
      try {
        script.init(context);
      } catch (ScriptException e) {
        _initialized = false;
        //e.fillInStackTrace();
        listener.error(new anvil.Location(_address.getURL()), e.getData().toString());
      } catch (Throwable t) {
        listener.error(null, t);
        anvil.Log.log().error("Initialization failed: "+script.getPathinfo(), t);
        _initialized = false;
      } finally {
        context.pop();
        context.destroy();
      }
    }
  }


  private static String mangle(String pathinfo)
  {
    int n = pathinfo.length();
    StringBuffer buffer = new StringBuffer(n + 10);
    char ch;
    int i = 0;
    if (n>0 && pathinfo.charAt(0) == '/') {
      i++;
    }
    for(; i<n; i++) {
      ch = pathinfo.charAt(i);
      if (ch == '/' || ch == '\\') {
        buffer.append('/');
        buffer.append('_');
      } /*else if (ch == '_') {
        buffer.append('_');
        buffer.append('_');
      }*/ else {
        if (!Character.isJavaIdentifierPart(ch)) {
          buffer.append('_');
          /*buffer.append(Integer.toHexString(ch));
          buffer.append('_');*/
        } else {
          buffer.append(ch);
        }
      }
    }
    return buffer.toString();
  }


  protected static void appendWithPrefix(StringBuffer buffer, int i)
  {
    if (i<10) {
      buffer.append('0');
    }
    buffer.append(i);
  }
 

  protected String addTimestamp(String mangled, long lastModified)
  {
    if (lastModified != -1) {
      StringBuffer buffer = new StringBuffer(mangled.length() + 18);
      LocalizationPreferences prefs = _address.getZone().getLocalizationPreferences();
      Calendar calendar = Calendar.getInstance(prefs.getTimezoneInstance(), prefs.getLocaleInstance());
      calendar.setTime(new Date(lastModified));
      buffer.append(mangled);
      buffer.append('_');
      buffer.append(calendar.get(Calendar.YEAR));
      appendWithPrefix(buffer, calendar.get(Calendar.MONTH)+1);
      appendWithPrefix(buffer, calendar.get(Calendar.DAY_OF_MONTH));
      buffer.append('_');
      appendWithPrefix(buffer, calendar.get(Calendar.HOUR_OF_DAY));
      appendWithPrefix(buffer, calendar.get(Calendar.MINUTE));
      appendWithPrefix(buffer, calendar.get(Calendar.SECOND));
      mangled = buffer.toString();
    }
    return mangled; 
  }


}
TOP

Related Classes of anvil.script.ModuleEnvelope

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.