aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderLogger.java
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderLogger.java')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderLogger.java327
1 files changed, 327 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderLogger.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderLogger.java
new file mode 100644
index 000000000..8548830bd
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderLogger.java
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.android.ide.eclipse.adt.internal.editors.layout.gle2;
+
+import com.android.annotations.NonNull;
+import com.android.annotations.Nullable;
+import com.android.ide.common.rendering.RenderSecurityManager;
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.ide.eclipse.adt.AdtPlugin;
+
+import org.eclipse.core.runtime.IStatus;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A {@link LayoutLog} which records the problems it encounters and offers them as a
+ * single summary at the end
+ */
+public class RenderLogger extends LayoutLog {
+ static final String TAG_MISSING_DIMENSION = "missing.dimension"; //$NON-NLS-1$
+
+ private final String mName;
+ private List<String> mFidelityWarnings;
+ private List<String> mWarnings;
+ private List<String> mErrors;
+ private boolean mHaveExceptions;
+ private List<String> mTags;
+ private List<Throwable> mTraces;
+ private static Set<String> sIgnoredFidelityWarnings;
+ private final Object mCredential;
+
+ /** Construct a logger for the given named layout */
+ RenderLogger(String name, Object credential) {
+ mName = name;
+ mCredential = credential;
+ }
+
+ /**
+ * Are there any logged errors or warnings during the render?
+ *
+ * @return true if there were problems during the render
+ */
+ public boolean hasProblems() {
+ return mFidelityWarnings != null || mErrors != null || mWarnings != null ||
+ mHaveExceptions;
+ }
+
+ /**
+ * Returns a list of traces encountered during rendering, or null if none
+ *
+ * @return a list of traces encountered during rendering, or null if none
+ */
+ @Nullable
+ public List<Throwable> getFirstTrace() {
+ return mTraces;
+ }
+
+ /**
+ * Returns a (possibly multi-line) description of all the problems
+ *
+ * @param includeFidelityWarnings if true, include fidelity warnings in the problem
+ * summary
+ * @return a string describing the rendering problems
+ */
+ @NonNull
+ public String getProblems(boolean includeFidelityWarnings) {
+ StringBuilder sb = new StringBuilder();
+
+ if (mErrors != null) {
+ for (String error : mErrors) {
+ sb.append(error).append('\n');
+ }
+ }
+
+ if (mWarnings != null) {
+ for (String warning : mWarnings) {
+ sb.append(warning).append('\n');
+ }
+ }
+
+ if (includeFidelityWarnings && mFidelityWarnings != null) {
+ sb.append("The graphics preview in the layout editor may not be accurate:\n");
+ for (String warning : mFidelityWarnings) {
+ sb.append("* ");
+ sb.append(warning).append('\n');
+ }
+ }
+
+ if (mHaveExceptions) {
+ sb.append("Exception details are logged in Window > Show View > Error Log");
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * Returns the fidelity warnings
+ *
+ * @return the fidelity warnings
+ */
+ @Nullable
+ public List<String> getFidelityWarnings() {
+ return mFidelityWarnings;
+ }
+
+ // ---- extends LayoutLog ----
+
+ @Override
+ public void error(String tag, String message, Object data) {
+ String description = describe(message);
+
+ appendToIdeLog(null, IStatus.ERROR, description);
+
+ // Workaround: older layout libraries don't provide a tag for this error
+ if (tag == null && message != null
+ && message.startsWith("Failed to find style ")) { //$NON-NLS-1$
+ tag = LayoutLog.TAG_RESOURCES_RESOLVE_THEME_ATTR;
+ }
+
+ addError(tag, description);
+ }
+
+ @Override
+ public void error(String tag, String message, Throwable throwable, Object data) {
+ String description = describe(message);
+ appendToIdeLog(throwable, IStatus.ERROR, description);
+
+ if (throwable != null) {
+ if (throwable instanceof ClassNotFoundException) {
+ // The project callback is given a chance to resolve classes,
+ // and when it fails, it will record it in its own list which
+ // is displayed in a special way (with action hyperlinks etc).
+ // Therefore, include these messages in the visible render log,
+ // especially since the user message from a ClassNotFoundException
+ // is really not helpful (it just lists the class name without
+ // even mentioning that it is a class-not-found exception.)
+ return;
+ }
+
+ if (description.equals(throwable.getLocalizedMessage()) ||
+ description.equals(throwable.getMessage())) {
+ description = "Exception raised during rendering: " + description;
+ }
+ recordThrowable(throwable);
+ mHaveExceptions = true;
+ }
+
+ addError(tag, description);
+ }
+
+ /**
+ * Record that the given exception was encountered during rendering
+ *
+ * @param throwable the exception that was raised
+ */
+ public void recordThrowable(@NonNull Throwable throwable) {
+ if (mTraces == null) {
+ mTraces = new ArrayList<Throwable>();
+ }
+ mTraces.add(throwable);
+ }
+
+ @Override
+ public void warning(String tag, String message, Object data) {
+ String description = describe(message);
+
+ boolean log = true;
+ if (TAG_RESOURCES_FORMAT.equals(tag)) {
+ if (description.equals("You must supply a layout_width attribute.") //$NON-NLS-1$
+ || description.equals("You must supply a layout_height attribute.")) {//$NON-NLS-1$
+ tag = TAG_MISSING_DIMENSION;
+ log = false;
+ }
+ }
+
+ if (log) {
+ appendToIdeLog(null, IStatus.WARNING, description);
+ }
+
+ addWarning(tag, description);
+ }
+
+ @Override
+ public void fidelityWarning(String tag, String message, Throwable throwable, Object data) {
+ if (sIgnoredFidelityWarnings != null && sIgnoredFidelityWarnings.contains(message)) {
+ return;
+ }
+
+ String description = describe(message);
+ appendToIdeLog(throwable, IStatus.ERROR, description);
+
+ if (throwable != null) {
+ mHaveExceptions = true;
+ }
+
+ addFidelityWarning(tag, description);
+ }
+
+ /**
+ * Ignore the given render fidelity warning for the current session
+ *
+ * @param message the message to be ignored for this session
+ */
+ public static void ignoreFidelityWarning(String message) {
+ if (sIgnoredFidelityWarnings == null) {
+ sIgnoredFidelityWarnings = new HashSet<String>();
+ }
+ sIgnoredFidelityWarnings.add(message);
+ }
+
+ @NonNull
+ private String describe(@Nullable String message) {
+ if (message == null) {
+ return "";
+ } else {
+ return message;
+ }
+ }
+
+ private void addWarning(String tag, String description) {
+ if (mWarnings == null) {
+ mWarnings = new ArrayList<String>();
+ } else if (mWarnings.contains(description)) {
+ // Avoid duplicates
+ return;
+ }
+ mWarnings.add(description);
+ addTag(tag);
+ }
+
+ private void addError(String tag, String description) {
+ if (mErrors == null) {
+ mErrors = new ArrayList<String>();
+ } else if (mErrors.contains(description)) {
+ // Avoid duplicates
+ return;
+ }
+ mErrors.add(description);
+ addTag(tag);
+ }
+
+ private void addFidelityWarning(String tag, String description) {
+ if (mFidelityWarnings == null) {
+ mFidelityWarnings = new ArrayList<String>();
+ } else if (mFidelityWarnings.contains(description)) {
+ // Avoid duplicates
+ return;
+ }
+ mFidelityWarnings.add(description);
+ addTag(tag);
+ }
+
+ // ---- Tags ----
+
+ private void addTag(String tag) {
+ if (tag != null) {
+ if (mTags == null) {
+ mTags = new ArrayList<String>();
+ }
+ mTags.add(tag);
+ }
+ }
+
+ /**
+ * Returns true if the given tag prefix has been seen
+ *
+ * @param prefix the tag prefix to look for
+ * @return true iff any tags with the given prefix was seen during the render
+ */
+ public boolean seenTagPrefix(String prefix) {
+ if (mTags != null) {
+ for (String tag : mTags) {
+ if (tag.startsWith(prefix)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns true if the given tag has been seen
+ *
+ * @param tag the tag to look for
+ * @return true iff the tag was seen during the render
+ */
+ public boolean seenTag(String tag) {
+ if (mTags != null) {
+ return mTags.contains(tag);
+ } else {
+ return false;
+ }
+ }
+
+ // Append the given message to the ADT log. Bypass the sandbox if necessary
+ // such that we can write to the log file.
+ private void appendToIdeLog(Throwable throwable, int severity, String description) {
+ boolean token = RenderSecurityManager.enterSafeRegion(mCredential);
+ try {
+ if (throwable != null) {
+ AdtPlugin.log(throwable, "%1$s: %2$s", mName, description);
+ } else {
+ AdtPlugin.log(severity, "%1$s: %2$s", mName, description);
+ }
+ } finally {
+ RenderSecurityManager.exitSafeRegion(token);
+ }
+ }
+}