Index: modules/quercus/src/com/caucho/quercus/env/Env.java =================================================================== --- modules/quercus/src/com/caucho/quercus/env/Env.java (revision 3799) +++ modules/quercus/src/com/caucho/quercus/env/Env.java (working copy) @@ -287,6 +287,8 @@ private Env _oldThreadEnv; + private ArrayList _destructors = new ArrayList(); + public Env(Quercus quercus, QuercusPage page, WriteStream out, @@ -579,6 +581,10 @@ return _isStrict; } + public final void addDestructor(AbstractFunction destructor, Value value) { + _destructors.add(new DestructorHolder(destructor, value)); + } + public void start() { _oldThreadEnv = _threadEnv.get(); @@ -4654,6 +4660,12 @@ { return _gzStream; } + + public void runDestructors() { + for(int i = 0; i < _destructors.size(); i++ ) + _destructors.get(i).call(this); + _destructors.clear(); + } /** * Called when the Env is no longer needed. @@ -4666,7 +4678,6 @@ while (_outputBuffer != null) { popOutputBuffer(); } - _freeFunList.free(_fun); } //catch (Exception e) { @@ -4752,7 +4763,22 @@ { return "Quercus[" + _selfPath + "] "; } + + static class DestructorHolder { + private Value instance; + private AbstractFunction destructor; + DestructorHolder(AbstractFunction destructor, Value instance) { + this.instance = instance; + this.destructor = destructor; + } + + void call(Env env) { + log.severe("Calling " + destructor + " on " + instance); + instance.callClassMethod(env, destructor, new Value[0]); + } + } + static class ClassKey { private final WeakReference _defRef; private final WeakReference _parentRef; Index: modules/quercus/src/com/caucho/quercus/program/ClassDef.java =================================================================== --- modules/quercus/src/com/caucho/quercus/program/ClassDef.java (revision 3799) +++ modules/quercus/src/com/caucho/quercus/program/ClassDef.java (working copy) @@ -41,201 +41,174 @@ * Represents a Quercus class definition */ abstract public class ClassDef { - private final static L10N L = new L10N(ClassDef.class); + private final static L10N L = new L10N(ClassDef.class); - private final Location _location; - private final String _name; - private final String _parentName; + private final Location _location; + private final String _name; + private final String _parentName; - private String []_ifaceList; + private String[] _ifaceList; - protected ClassDef(Location location, - String name, - String parentName, - String []ifaceList) - { - _location = location; - _name = name; - _parentName = parentName; - _ifaceList = ifaceList; - } + protected ClassDef(Location location, String name, String parentName, + String[] ifaceList) { + _location = location; + _name = name; + _parentName = parentName; + _ifaceList = ifaceList; + } - /** - * Returns the location for where the class was defined, null if it is unknown. - */ - public Location getLocation() - { - return _location; - } + /** + * Returns the location for where the class was defined, null if it is + * unknown. + */ + public Location getLocation() { + return _location; + } - /** - * Returns the name. - */ - public String getName() - { - return _name; - } + /** + * Returns the name. + */ + public String getName() { + return _name; + } - /** - * Returns the parent name. - */ - public String getParentName() - { - return _parentName; - } - - /* - * Returns the name of the extension that this class is part of. - */ - public String getExtension() - { - return null; - } + /** + * Returns the parent name. + */ + public String getParentName() { + return _parentName; + } - protected void addInterface(String iface) - { - for (int i = 0; i < _ifaceList.length; i++) - if (_ifaceList[i].equals(iface)) - return; + /* + * Returns the name of the extension that this class is part of. + */ + public String getExtension() { + return null; + } - String[] ifaceList = new String[_ifaceList.length + 1]; + protected void addInterface(String iface) { + for (int i = 0; i < _ifaceList.length; i++) + if (_ifaceList[i].equals(iface)) + return; - System.arraycopy(_ifaceList, 0, ifaceList, 0, _ifaceList.length); - ifaceList[ifaceList.length - 1] = iface; + String[] ifaceList = new String[_ifaceList.length + 1]; - _ifaceList = ifaceList; - } + System.arraycopy(_ifaceList, 0, ifaceList, 0, _ifaceList.length); + ifaceList[ifaceList.length - 1] = iface; - public void init() - { - } - - /** - * Returns the interfaces. - */ - public String []getInterfaces() - { - return _ifaceList; - } + _ifaceList = ifaceList; + } - /** - * Return true for an abstract class. - */ - public boolean isAbstract() - { - return false; - } + public void init() { + } - /** - * Return true for an interface class. - */ - public boolean isInterface() - { - return false; - } - - /* - * Returns true for a final class. - */ - public boolean isFinal() - { - return false; - } - - /* - * - */ - public boolean hasNonPublicMethods() - { - return false; - } - - /** - * Initialize the quercus class. - */ - public void initClass(QuercusClass cl) - { - } + /** + * Returns the interfaces. + */ + public String[] getInterfaces() { + return _ifaceList; + } - /** - * Creates a new instance. - */ - public ObjectValue newInstance(Env env, QuercusClass qcl) - { - if (isAbstract()) { - throw env.createErrorException(L.l("abstract class '{0}' cannot be instantiated.", - getName())); - } - else if (isInterface()) { - throw env.createErrorException(L.l("interface '{0}' cannot be instantiated.", - getName())); - } - - return new ObjectExtValue(qcl); - } + /** + * Return true for an abstract class. + */ + public boolean isAbstract() { + return false; + } - /** - * Creates a new instance. - */ - public Value callNew(Env env, Expr []args) - { - return null; - } + /** + * Return true for an interface class. + */ + public boolean isInterface() { + return false; + } - /** - * Creates a new instance. - */ - public Value callNew(Env env, Value []args) - { - return null; - } + /* + * Returns true for a final class. + */ + public boolean isFinal() { + return false; + } - /** - * Returns value for instanceof. - */ - public boolean isA(String name) - { - if (_name.equalsIgnoreCase(name)) - return true; + /* + * + */ + public boolean hasNonPublicMethods() { + return false; + } - for (int i = 0; i < _ifaceList.length; i++) { - if (_ifaceList[i].equalsIgnoreCase(name)) - return true; - } + /** + * Initialize the quercus class. + */ + public void initClass(QuercusClass cl) { + } - return false; - } + /** + * Creates a new instance. + */ + public ObjectValue newInstance(Env env, QuercusClass qcl) { + if (isAbstract()) { + throw env.createErrorException(L.l( + "abstract class '{0}' cannot be instantiated.", getName())); + } else if (isInterface()) { + throw env.createErrorException(L.l( + "interface '{0}' cannot be instantiated.", getName())); + } - /** - * Returns the constructor - */ - abstract public AbstractFunction findConstructor(); + return new ObjectExtValue(qcl); + } - /** - * Finds the matching constant - */ - public Expr findConstant(String name) - { - return null; - } + /** + * Creates a new instance. + */ + public Value callNew(Env env, Expr[] args) { + return null; + } - public String toString() - { - return getClass().getSimpleName() - + "@" - + System.identityHashCode(this) - + "[" + _name + "]"; - } + /** + * Creates a new instance. + */ + public Value callNew(Env env, Value[] args) { + return null; + } - public Set> fieldSet() - { - return null; - } - - public Set> functionSet() - { - return null; - } + /** + * Returns value for instanceof. + */ + public boolean isA(String name) { + if (_name.equalsIgnoreCase(name)) + return true; -} + for (int i = 0; i < _ifaceList.length; i++) { + if (_ifaceList[i].equalsIgnoreCase(name)) + return true; + } + return false; + } + + /** + * Returns the constructor + */ + abstract public AbstractFunction findConstructor(); + + /** + * Finds the matching constant + */ + public Expr findConstant(String name) { + return null; + } + + public String toString() { + return getClass().getSimpleName() + "@" + System.identityHashCode(this) + + "[" + _name + "]"; + } + + public Set> fieldSet() { + return null; + } + + public Set> functionSet() { + return null; + } +} Index: modules/quercus/src/com/caucho/quercus/program/InterpretedClassDef.java =================================================================== --- modules/quercus/src/com/caucho/quercus/program/InterpretedClassDef.java (revision 3799) +++ modules/quercus/src/com/caucho/quercus/program/InterpretedClassDef.java (working copy) @@ -281,6 +281,7 @@ for (Map.Entry entry : _fieldMap.entrySet()) { object.initField(entry.getKey(), entry.getValue().eval(env).copy()); } + if(_destructor != null) env.addDestructor(_destructor, value); } /** Index: modules/quercus/src/com/caucho/quercus/page/QuercusPage.java =================================================================== --- modules/quercus/src/com/caucho/quercus/page/QuercusPage.java (revision 3799) +++ modules/quercus/src/com/caucho/quercus/page/QuercusPage.java (working copy) @@ -134,6 +134,7 @@ return NullValue.NULL; } finally { + env.runDestructors(); env.setPwd(oldPwd); } }