/* * Copyright 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.google.gwt.core.client; import com.google.gwt.core.client.impl.Impl; /** * Supports core functionality that in some cases requires direct support from * the compiler and runtime systems such as runtime type information and * deferred binding. */ public final class GWT { /** * This interface is used to catch exceptions at the "top level" just before * they escape to the browser. This is used in places where the browser calls * into user code such as event callbacks, timers, and RPC. * * In Development Mode, the default handler prints a stack trace to the log * window. In Production Mode, the default handler is null and thus exceptions * are allowed to escape, which provides an opportunity to use a JavaScript * debugger. */ public interface UncaughtExceptionHandler { void onUncaughtException(Throwable e); } /** * An {@link UncaughtExceptionHandler} that logs errors to * {@link GWT#log(String, Throwable)}. This is the default exception handler * in Development Mode. In Production Mode, the default exception handler is * <code>null</code>. */ private static final class DefaultUncaughtExceptionHandler implements UncaughtExceptionHandler { @Override public void onUncaughtException(Throwable e) { log("Uncaught exception escaped", e); } } /** * This constant is used by {@link #getPermutationStrongName} when running in * Development Mode. */ public static final String HOSTED_MODE_PERMUTATION_STRONG_NAME = "HostedMode"; /** * Defaults to <code>null</code> in Production Mode and an instance of * {@link DefaultUncaughtExceptionHandler} in Development Mode. */ private static UncaughtExceptionHandler uncaughtExceptionHandler = null; /** * Instantiates a class via deferred binding. * * <p> * The argument to {@link #create(Class)} <i>must</i> be a class literal * because the Production Mode compiler must be able to statically determine * the requested type at compile-time. This can be tricky because using a * {@link Class} variable may appear to work correctly in Development Mode. * </p> * * @param classLiteral a class literal specifying the base class to be * instantiated * @return the new instance, which must be cast to the requested class */ public static <T> T create(Class<?> classLiteral) { /* * In Production Mode, the compiler directly replaces calls to this method * with a new Object() type expression of the correct rebound type. */ return com.google.gwt.core.shared.GWT.<T>create(classLiteral); } public static void exportUnloadModule() { Impl.exportUnloadModule(); } /** * Gets the URL prefix of the hosting page, useful for prepending to relative * paths of resources which may be relative to the host page. Typically, you * should use {@link #getModuleBaseURL()} unless you have a specific reason to * load a resource relative to the host page. * * @return if non-empty, the base URL is guaranteed to end with a slash */ public static String getHostPageBaseURL() { return Impl.getHostPageBaseURL(); } /** * Gets the URL prefix that should be prepended to URLs that point to * static files generated by the GWT compiler, such as files in the * module's public path. * * <p> * Normally this will be the same value as {@link #getModuleBaseURL}, but * may be different when a GWT app is configured to get its static resources * from a different server. * </p> * * @return if non-empty, the base URL is guaranteed to end with a slash */ public static String getModuleBaseForStaticFiles() { return Impl.getModuleBaseURLForStaticFiles(); } /** * Gets the URL prefix that should be prepended to URLs that * are intended to be module-relative, such as RPC entry points. * * <p>If the URL points to an output file of the GWT compiler (such as * a file in the public path), use {@link #getModuleBaseForStaticFiles()} * instead.</p> * * @return if non-empty, the base URL is guaranteed to end with a slash */ public static String getModuleBaseURL() { return Impl.getModuleBaseURL(); } /** * Gets the name of the running module. */ public static String getModuleName() { return Impl.getModuleName(); } /** * Returns the permutation's strong name. This can be used to distinguish * between different permutations of the same module. In Development Mode, * this method will return {@value #HOSTED_MODE_PERMUTATION_STRONG_NAME}. */ public static String getPermutationStrongName() { if (GWT.isScript()) { return Impl.getPermutationStrongName(); } else { return HOSTED_MODE_PERMUTATION_STRONG_NAME; } } /** * @deprecated Use {@link Object#getClass()}, {@link Class#getName()} */ @Deprecated public static String getTypeName(Object o) { return (o == null) ? null : o.getClass().getName(); } /** * Returns the currently active uncaughtExceptionHandler. * * @return the currently active handler, or null if no handler is active. * * @see #maybeReportUncaughtException(Throwable) */ public static UncaughtExceptionHandler getUncaughtExceptionHandler() { return uncaughtExceptionHandler; } /** * Reports an exception caught at the "top level" to a handler set via * {@link #setUncaughtExceptionHandler(UncaughtExceptionHandler)}. This is * used in places where the browser calls into user code such as event * callbacks, timers, and RPC. See {@link Impl#entry0} for an example how to * handle this correctly. * <p> * This method is a no-op if no handler is set. */ public static void maybeReportUncaughtException(Throwable t) { Impl.maybeReportUncaughtException(uncaughtExceptionHandler, t); } /** * Returns the empty string when running in Production Mode, but returns a * unique string for each thread in Development Mode (for example, different * windows accessing the dev mode server will each have a unique id, and * hitting refresh without restarting dev mode will result in a new unique id * for a particular window. * * TODO(unnurg): Remove this function once Dev Mode rewriting classes are in * gwt-dev. */ public static String getUniqueThreadId() { return com.google.gwt.core.shared.GWT.getUniqueThreadId(); } public static String getVersion() { String version = com.google.gwt.core.shared.GWT.getVersion(); if (version == null) { version = getVersion0(); } return version; } /** * Returns <code>true</code> when running inside the normal GWT environment, * either in Development Mode or Production Mode. Returns <code>false</code> * if this code is running in a plain JVM. This might happen when running * shared code on the server, or during the bootstrap sequence of a * GWTTestCase test. */ public static boolean isClient() { return com.google.gwt.core.shared.GWT.isClient(); } /** * Returns <code>true</code> when running in production mode. Returns * <code>false</code> when running either in development mode, or when running * in a plain JVM. */ public static boolean isProdMode() { return com.google.gwt.core.shared.GWT.isProdMode(); } /** * Determines whether or not the running program is script or bytecode. */ public static boolean isScript() { return com.google.gwt.core.shared.GWT.isScript(); } /** * Logs a message to the development shell logger in Development Mode. Calls * are optimized out in Production Mode. */ public static void log(String message) { com.google.gwt.core.shared.GWT.log(message); } /** * Logs a message to the development shell logger in Development Mode. Calls * are optimized out in Production Mode. */ public static void log(String message, Throwable e) { com.google.gwt.core.shared.GWT.log(message, e); } /** * The same as {@link #runAsync(RunAsyncCallback)}, except with an extra * parameter to provide a name for the call. The name parameter should be * supplied with a class literal. No two runAsync calls in the same program * should use the same name. */ @SuppressWarnings("unused") // parameter will be used following replacement public static void runAsync(Class<?> name, RunAsyncCallback callback) { callback.onSuccess(); } /** * Run the specified callback once the necessary code for it has been loaded. */ public static void runAsync(RunAsyncCallback callback) { callback.onSuccess(); } /** * Sets a custom uncaught exception handler. See * {@link #getUncaughtExceptionHandler()} for details. * * @param handler the handler that should be called when an exception is * about to escape to the browser, or <code>null</code> to clear the * handler and allow exceptions to escape. */ public static void setUncaughtExceptionHandler( UncaughtExceptionHandler handler) { uncaughtExceptionHandler = handler; } /** * Called via reflection in Development Mode; do not ever call this method in * Production Mode. */ static void setBridge(GWTBridge bridge) { com.google.gwt.core.shared.GWT.setBridge(bridge); if (bridge != null) { setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler()); } } private static native String getVersion0() /*-{ return $gwt_version; }-*/; /** * If enabled via <set-property name="gwt.unloadEnabled" value="true"/> invoking this method causes the module * to be removed from memory and all {@link com.google.gwt.core.client.impl.Disposable} instances to be * cleaned up. This method is not typically called by the GWT module itself, but exported so that another module * may call it. * @see com.google.gwt.core.client.GWT#exportUnloadModule() */ private static void unloadModule() { Impl.unloadModule(); } }