Package anvil.script

Source Code of anvil.script.Smith

/*
* $Id: Smith.java,v 1.12 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 java.io.IOException;
import java.io.OutputStream;
import java.security.PermissionCollection;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import anvil.codec.School;
import anvil.server.Address;
import anvil.server.Resource;
import anvil.server.ContainerException;
import anvil.server.MemoryLoader;
import anvil.server.ZoneClassLoader;
import anvil.server.Zone;
import anvil.java.util.Hashlist;
import anvil.Location;
import anvil.ErrorListener;
import anvil.ErrorListenerImpl;
import anvil.ForgingException;

/**
* class Smith
*
* @author: Jani Lehtim�ki
*/
public class Smith implements ErrorListener, School
{
  protected static final Object LOAD_LOCK = new Object();

  protected ModuleCache   _cache;
  protected Address       _address;
  protected Hashlist      _forged = new Hashlist();
  protected ErrorListener _listener = null;
  protected HashSet       _loading = new HashSet();
  protected HashSet       _notimported = null;
  protected boolean       _changed = false;
  protected MemoryLoader  _loader = null;

  public Smith(ModuleCache cache, Address address)
  {
    _cache = cache;
    _address = address;
  }

  protected ErrorListener getListener()
  {
    ErrorListener listener = _listener;
    if (listener == null) {
      _listener = listener = new ErrorListenerImpl();
    }
    return listener;
  }
 

  public void error(Location location, Throwable throwable)
  {
    getListener().error(location, throwable);
  }


  public void error(Location location, String message)
  {
    getListener().error(location, message);
  }


  public int errors()
  {
    if (_listener == null) {
      return 0;
    } else {
      return _listener.errors();
    }
  }


  public Enumeration getEvents()
  {
    return getListener().getEvents();
  }


  public void merge(ErrorListener listener)
  {
    getListener().merge(listener);
  }


  public Address getAddress()
  {
    return _address;
  }


  private void purge(ModuleEnvelope envelope)
  {
    Address a = envelope.getAddress();
    _cache.purge(a);
    _forged.remove(a);
  }
 

  protected void linkImports(ModuleEnvelope envelope)
  {
    Iterator iter = envelope.getModule().getDependencies();
    while(iter.hasNext()) {
      Dependency dep = (Dependency)iter.next();
      dep.setScript((ModuleEnvelope)_forged.get(dep.getAddress()));
    }
  }

 
  protected boolean forgeImports(ModuleEnvelope envelope)
    throws IOException, ForgingException
  {
    boolean doparse = false;
    Module script = envelope.getModule();
    boolean failed = false;
    Iterator iter = script.getDependencies();
   
    Address source = envelope.getAddress();
    String sourcepath = source.getPathinfo();
    Zone zone = source.getZone();
    boolean hasPolicy = zone.getDomain().hasPolicy();
   
    while(iter.hasNext()) {
      Dependency dep = (Dependency)iter.next();
      try {
     
        Address target = dep.getAddress();
        if (hasPolicy) {
          String targetpath = target.getPathinfo();
          if (!ImportPermission.onSameDir(sourcepath, targetpath)) {
            if (!zone.checkPermission(new ImportPermission(targetpath))) {
              error(dep.getLocation(), "Access denied: "+targetpath);
            }
          }
        }
       
        ModuleEnvelope imported = forge(target);
        if (imported != null) {
          boolean source_compiled = envelope.isCompiled();
          boolean target_compiled = imported.isCompiled();
          if (source_compiled) {
            if (target_compiled) {
              // check signatures
              if (!imported.getDescriptor().equals(dep.getDescriptor())) {
                doparse = true;
              }
            } else {
              doparse = true;
            }
          } else {
            // source already parsed
          }
        } else {
          boolean report_error = true;
          Address addr = dep.getAddress();
          if (_notimported == null) {
            _notimported = new HashSet();
            _notimported.add(addr);
          } else {
            if (_notimported.contains(addr)) {
              report_error = false;
            } else {
              _notimported.add(addr);
            }
          }
          if (report_error) {
            error(dep.getLocation(), "Couldn't import: "+dep.getPathinfo());
          }
        }
      } catch (IOException e) {
        error(dep.getLocation(), "Resource not found: "+dep.getPathinfo());
      } catch (ForgingException e) {
        merge(e.getErrorListener());
      }
    }
    return doparse;
  }


  public ModuleEnvelope get(Address address)
  {
    return (ModuleEnvelope)_forged.get(address);
  }

 
  protected ModuleEnvelope load(Address address)
    throws IOException, ForgingException
  {
    ModuleEnvelope envelope = _cache.get(address);
    Resource resource = null;
    boolean reload = false;
    if (envelope != null) {
      long lastmodified = envelope.getLastModified();
      if ((lastmodified != -1) && address.getZone().shouldInvalidate()) {
        resource = address.openResource();
        if (resource.getLastModified() > lastmodified) {
          reload = true;
        }
      }   
    } else {
      resource = address.openResource();
      reload = true;
    }
    if (reload) {
      _changed = true;
      envelope = new ModuleEnvelope(_cache, address, resource);
    }
    _forged.insert(address, envelope);
    return envelope;
  }
 
 
  public ModuleEnvelope forge() throws IOException, ForgingException
  {
    ModuleEnvelope env = forge(_address);
    temper();
    return env;
  }


  protected ModuleEnvelope forge(Address address)
    throws IOException, ForgingException
  {
    ModuleEnvelope envelope = (ModuleEnvelope)_forged.get(address);
    if (_loading.contains(address)) {
      return envelope;
    }
    _loading.add(address);
    if (envelope != null) {
      _forged.remove(address);
      _forged.insert(address, envelope);
    } else {
      envelope = load(address);
    }
    if (forgeImports(envelope)) {
      purge(envelope);
      _changed = true;
      envelope = envelope.forge();
      _forged.put(address, envelope);
    }
    _loading.remove(address);
    return envelope;
  }
 
 
  protected ModuleEnvelope[] getEnvelopes()
  {
    return (ModuleEnvelope[])_forged.toArray(ModuleEnvelope.class);
  }


  protected void errorCheck() throws ForgingException
  {
    if (_listener != null) {
      throw new ForgingException(_listener);
    }   
  }
 
 
  protected void temper() throws ForgingException
  {
    ModuleEnvelope[] e = getEnvelopes();
    int n = e.length;
   
    try {

      errorCheck();

      if (_changed) {
        for(int i=0; i<n; i++) {
          linkImports(e[i]);
        }

        for(int i=0; i<n; i++) {
          e[i].importExternals(this);
        }

        Resolver resolver = new Resolver(this);
        for(int i=0; i<n; i++) {
          e[i].resolve(resolver);
        }

        errorCheck();

        Verifier verifier = new Verifier(this);
        for(int i=0; i<n; i++) {
          e[i].verifyPassOne(verifier);
        }

        errorCheck();

        for(int i=0; i<n; i++) {
          e[i].verifyPassTwo(verifier);
        }

        errorCheck();

        for(int i=0; i<n; i++) {
          e[i].check(this);
        }

        errorCheck();

        _loader = new MemoryLoader(_address.getZone().getCompilerPreferences());
       
        for(int i=0; i<n; i++) {
          e[i].compile(this);
        }

        errorCheck();
        synchronized (LOAD_LOCK) {
          ZoneClassLoader clsldr = _address.getZone().getClassLoader();
          try {
            clsldr.setMemoryLoader(_loader);

            for(int i=0; i<n; i++) {
              if (!e[i].loadClass()) {
                error(null, "Loading of "+e[i].getAddress()+" failed");
              }
            }
          } finally {
            clsldr.setMemoryLoader(null);
          }

          errorCheck();

          for(int i=0; i<n; i++) {
            linkImports(e[i]);
          }

          _cache.put(e);
         
        }

      }

      for(int i=0; i<n; i++) {
        e[i].init(this);
      }     

      errorCheck();
   
    } finally {
      if (_loader != null) {
        _loader.destroy();
      }
    }

  }

 
  public OutputStream createClassRoom(String name) throws IOException
  {
    return _loader.createClassRoom(name);
  }

}
TOP

Related Classes of anvil.script.Smith

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.