001: /*
002: * Copyright 2007 Google Inc.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005: * use this file except in compliance with the License. You may obtain a copy of
006: * the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013: * License for the specific language governing permissions and limitations under
014: * the License.
015: */
016: package com.google.gwt.dev.shell;
017:
018: import com.google.gwt.core.ext.BadPropertyValueException;
019: import com.google.gwt.core.ext.PropertyOracle;
020: import com.google.gwt.core.ext.TreeLogger;
021: import com.google.gwt.dev.cfg.Properties;
022: import com.google.gwt.dev.cfg.Property;
023:
024: import java.util.HashMap;
025: import java.util.Map;
026:
027: /**
028: * Implements a {@link PropertyOracle} in terms of a module space, which makes
029: * it possible to execute property providers.
030: */
031: public class ModuleSpacePropertyOracle implements PropertyOracle {
032:
033: private final Map<String, String> prevAnswers = new HashMap<String, String>();
034:
035: private final Properties props;
036:
037: private final ModuleSpace space;
038:
039: public ModuleSpacePropertyOracle(Properties props, ModuleSpace space) {
040: this .space = space;
041: this .props = props;
042: }
043:
044: /**
045: * Executes JavaScript to find the property value.
046: */
047: public String getPropertyValue(TreeLogger logger,
048: String propertyName) throws BadPropertyValueException {
049: if (propertyName == null) {
050: throw new NullPointerException("propertyName");
051: }
052:
053: Property prop = props.find(propertyName);
054: if (prop == null) {
055: // Don't know this property; that's not good.
056: //
057: throw new BadPropertyValueException(propertyName);
058: }
059:
060: // Check if this property has already been queried for; if so, return
061: // the same answer. This is necessary to match web mode behavior since
062: // property providers are only called once. We cache even values that
063: // cause exceptions to be thrown to make sure we are consistent even
064: // in throwing exceptions for the same property.
065: if (prevAnswers.containsKey(propertyName)) {
066: return prevAnswers.get(propertyName);
067: } else {
068: String value = computePropertyValue(logger, propertyName,
069: prop);
070: prevAnswers.put(propertyName, value);
071: return value;
072: }
073: }
074:
075: /**
076: * Returns the value of the specified property.
077: *
078: * @throws BadPropertyValueException if the property value could not be
079: * computed, or if the returned result is not a legal value for this
080: * property.
081: */
082: private String computePropertyValue(TreeLogger logger,
083: String propertyName, Property prop)
084: throws BadPropertyValueException {
085: String value;
086: // If there is an active value, use that.
087: //
088: value = prop.getActiveValue();
089:
090: // In case there isn't an active value...
091: if (value == null) {
092: // Invokes the script function.
093: //
094: try {
095: // Invoke the property provider function in JavaScript.
096: //
097: value = space.invokeNativeString("__gwt_getProperty",
098: null, new Class[] { String.class },
099: new Object[] { prop.getName() });
100: } catch (Throwable e) {
101: // Treat as an unknown value.
102: //
103: String msg = "Error while executing the JavaScript provider for property '"
104: + propertyName + "'";
105: logger.log(TreeLogger.ERROR, msg, e);
106: throw new BadPropertyValueException(propertyName,
107: "<failed to compute>");
108: }
109: }
110:
111: // value may be null if the provider returned an unknown property value.
112: if (prop.isKnownValue(value)) {
113: return value;
114: } else {
115: // Bad value due to the provider returning an unknown value.
116: // The fact that the provider returned an invalid value will also
117: // have been reported to the JS bad property value handler function.
118: throw new BadPropertyValueException(propertyName, value);
119: }
120: }
121: }
|