001: /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
002: *
003: * ***** BEGIN LICENSE BLOCK *****
004: * Version: MPL 1.1/GPL 2.0
005: *
006: * The contents of this file are subject to the Mozilla Public License Version
007: * 1.1 (the "License"); you may not use this file except in compliance with
008: * the License. You may obtain a copy of the License at
009: * http://www.mozilla.org/MPL/
010: *
011: * Software distributed under the License is distributed on an "AS IS" basis,
012: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
013: * for the specific language governing rights and limitations under the
014: * License.
015: *
016: * The Original Code is Rhino code, released
017: * May 6, 1999.
018: *
019: * The Initial Developer of the Original Code is
020: * Netscape Communications Corporation.
021: * Portions created by the Initial Developer are Copyright (C) 1997-2000
022: * the Initial Developer. All Rights Reserved.
023: *
024: * Contributor(s):
025: * Norris Boyd
026: * Igor Bukanov
027: *
028: * Alternatively, the contents of this file may be used under the terms of
029: * the GNU General Public License Version 2 or later (the "GPL"), in which
030: * case the provisions of the GPL are applicable instead of those above. If
031: * you wish to allow use of your version of this file only under the terms of
032: * the GPL and not to allow others to use your version of this file under the
033: * MPL, indicate your decision by deleting the provisions above and replacing
034: * them with the notice and other provisions required by the GPL. If you do
035: * not delete the provisions above, a recipient may use your version of this
036: * file under either the MPL or the GPL.
037: *
038: * ***** END LICENSE BLOCK ***** */
039:
040: package org.mozilla.javascript;
041:
042: import java.lang.reflect.*;
043:
044: /**
045: * Avoid loading classes unless they are used.
046: *
047: * <p> This improves startup time and average memory usage.
048: */
049: public final class LazilyLoadedCtor implements java.io.Serializable {
050: private static final long serialVersionUID = 1L;
051:
052: private static final int STATE_BEFORE_INIT = 0;
053: private static final int STATE_INITIALIZING = 1;
054: private static final int STATE_WITH_VALUE = 2;
055:
056: private final ScriptableObject scope;
057: private final String propertyName;
058: private final String className;
059: private final boolean sealed;
060: private Object initializedValue;
061: private int state;
062:
063: public LazilyLoadedCtor(ScriptableObject scope,
064: String propertyName, String className, boolean sealed) {
065:
066: this .scope = scope;
067: this .propertyName = propertyName;
068: this .className = className;
069: this .sealed = sealed;
070: this .state = STATE_BEFORE_INIT;
071:
072: scope.addLazilyInitializedValue(propertyName, 0, this ,
073: ScriptableObject.DONTENUM);
074: }
075:
076: void init() {
077: synchronized (this ) {
078: if (state == STATE_INITIALIZING)
079: throw new IllegalStateException(
080: "Recursive initialization for " + propertyName);
081: if (state == STATE_BEFORE_INIT) {
082: state = STATE_INITIALIZING;
083: // Set value now to have something to set in finally block if
084: // buildValue throws.
085: Object value = Scriptable.NOT_FOUND;
086: try {
087: value = buildValue();
088: } finally {
089: initializedValue = value;
090: state = STATE_WITH_VALUE;
091: }
092: }
093: }
094: }
095:
096: Object getValue() {
097: if (state != STATE_WITH_VALUE)
098: throw new IllegalStateException(propertyName);
099: return initializedValue;
100: }
101:
102: private Object buildValue() {
103: Class cl = Kit.classOrNull(className);
104: if (cl != null) {
105: try {
106: Object value = ScriptableObject.buildClassCtor(scope,
107: cl, sealed, false);
108: if (value != null) {
109: return value;
110: } else {
111: // cl has own static initializer which is expected
112: // to set the property on its own.
113: value = scope.get(propertyName, scope);
114: if (value != Scriptable.NOT_FOUND)
115: return value;
116: }
117: } catch (InvocationTargetException ex) {
118: Throwable target = ex.getTargetException();
119: if (target instanceof RuntimeException) {
120: throw (RuntimeException) target;
121: }
122: } catch (RhinoException ex) {
123: } catch (InstantiationException ex) {
124: } catch (IllegalAccessException ex) {
125: } catch (SecurityException ex) {
126: }
127: }
128: return Scriptable.NOT_FOUND;
129: }
130:
131: }
|