All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.glassfish.jersey.internal.Errors Maven / Gradle / Ivy

Go to download

A bundle project producing JAX-RS RI bundles. The primary artifact is an "all-in-one" OSGi-fied JAX-RS RI bundle (jaxrs-ri.jar). Attached to that are two compressed JAX-RS RI archives. The first archive (jaxrs-ri.zip) consists of binary RI bits and contains the API jar (under "api" directory), RI libraries (under "lib" directory) as well as all external RI dependencies (under "ext" directory). The secondary archive (jaxrs-ri-src.zip) contains buildable JAX-RS RI source bundle and contains the API jar (under "api" directory), RI sources (under "src" directory) as well as all external RI dependencies (under "ext" directory). The second archive also contains "build.xml" ANT script that builds the RI sources. To build the JAX-RS RI simply unzip the archive, cd to the created jaxrs-ri directory and invoke "ant" from the command line.

There is a newer version: 3.1.9
Show newest version
/*
 * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package org.glassfish.jersey.internal;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.logging.Logger;

import org.glassfish.jersey.Severity;
import org.glassfish.jersey.internal.util.Producer;

/**
 * Errors utility used to file processing messages (e.g. validation, provider, resource building errors, hint).
 * 

* Error filing methods ({@code #warning}, {@code #error}, {@code #fatal}) can be invoked only in the "error scope" which is * created by {@link #process(Producer)} or * {@link #processWithException(Producer)} methods. Filed error messages are present also in this * scope. *

* TODO do not use static thread local? * * @author Michal Gajdos */ public class Errors { private static final Logger LOGGER = Logger.getLogger(Errors.class.getName()); private static final ThreadLocal errors = new ThreadLocal(); /** * Add an error to the list of messages. * * @param message message of the error. * @param severity indicates severity of added error. */ public static void error(final String message, Severity severity) { error(null, message, severity); } /** * Add an error to the list of messages. * * @param source source of the error. * @param message message of the error. * @param severity indicates severity of added error. */ public static void error(final Object source, final String message, final Severity severity) { getInstance().issues.add(new ErrorMessage(source, message, severity)); } /** * Add a fatal error to the list of messages. * * @param source source of the error. * @param message message of the error. */ public static void fatal(final Object source, final String message) { error(source, message, Severity.FATAL); } /** * Add a warning to the list of messages. * * @param source source of the error. * @param message message of the error. */ public static void warning(final Object source, final String message) { error(source, message, Severity.WARNING); } /** * Add a hint to the list of messages. * * @param source source of the error. * @param message message of the error. */ public static void hint(final Object source, final String message) { getInstance().issues.add(new ErrorMessage(source, message, Severity.HINT)); } /** * Log errors and throw an exception if there are any fatal issues detected and * the {@code throwException} flag has been set to {@code true}. * * @param throwException if set to {@code true}, any fatal issues will cause a {@link ErrorMessagesException} * to be thrown. */ private static void processErrors(final boolean throwException) { final List errors = new ArrayList(Errors.errors.get().issues); boolean isFatal = logErrors(errors); if (throwException && isFatal) { throw new ErrorMessagesException(errors); } } /** * Log errors and return a status flag indicating whether a fatal issue has been found * in the error collection. *

* The {@code afterMark} flag indicates whether only those issues should be logged that were * added after a {@link #mark() mark has been set}. *

* * @param afterMark if {@code true}, only issues added after a mark has been set are returned, * if {@code false} all issues are returned. * @return {@code true} if there are any fatal issues present in the collection, {@code false} * otherwise. */ public static boolean logErrors(final boolean afterMark) { return logErrors(getInstance()._getErrorMessages(afterMark)); } /** * Log supplied errors and return a status flag indicating whether a fatal issue has been found * in the error collection. * * @param errors a collection of errors to be logged. * @return {@code true} if there are any fatal issues present in the collection, {@code false} * otherwise. */ private static boolean logErrors(final Collection errors) { boolean isFatal = false; if (!errors.isEmpty()) { StringBuilder fatals = new StringBuilder("\n"); StringBuilder warnings = new StringBuilder(); StringBuilder hints = new StringBuilder(); for (final ErrorMessage error : errors) { switch (error.getSeverity()) { case FATAL: isFatal = true; fatals.append(LocalizationMessages.ERROR_MSG(error.getMessage())).append('\n'); break; case WARNING: warnings.append(LocalizationMessages.WARNING_MSG(error.getMessage())).append('\n'); break; case HINT: hints.append(LocalizationMessages.HINT_MSG(error.getMessage())).append('\n'); break; } } if (isFatal) { LOGGER.severe(LocalizationMessages.ERRORS_AND_WARNINGS_DETECTED(fatals.append(warnings) .append(hints).toString())); } else { if (warnings.length() > 0) { LOGGER.warning(LocalizationMessages.WARNINGS_DETECTED(warnings.toString())); } if (hints.length() > 0) { LOGGER.config(LocalizationMessages.HINTS_DETECTED(hints.toString())); } } } return isFatal; } /** * Check whether a fatal error is present in the list of all messages. * * @return {@code true} if there are any fatal issues in this error context, {@code false} otherwise. */ public static boolean fatalIssuesFound() { for (final ErrorMessage message : getInstance().issues) { if (message.getSeverity() == Severity.FATAL) { return true; } } return false; } /** * Invoke given producer task and gather errors. *

* After the task is complete all gathered errors are logged. No exception is thrown * even if there is a fatal error present in the list of errors. * * @param producer producer task to be invoked. * @return the result produced by the task. */ public static T process(final Producer producer) { return process(producer, false); } /** * Invoke given callable task and gather messages. *

* After the task is complete all gathered errors are logged. Any exception thrown * by the throwable is re-thrown. * * @param task callable task to be invoked. * @return the result produced by the task. * @throws Exception exception thrown by the task. */ public static T process(final Callable task) throws Exception { return process(task, true); } /** * Invoke given producer task and gather messages. *

* After the task is complete all gathered errors are logged. If there is a fatal error * present in the list of errors an {@link ErrorMessagesException exception} is thrown. * * @param producer producer task to be invoked. * @return the result produced by the task. */ public static T processWithException(final Producer producer) { return process(producer, true); } /** * Invoke given task and gather messages. *

* After the task is complete all gathered errors are logged. No exception is thrown * even if there is a fatal error present in the list of errors. * * @param task task to be invoked. */ public static void process(final Runnable task) { process(new Producer() { @Override public Void call() { task.run(); return null; } }, false); } /** * Invoke given task and gather messages. *

* After the task is complete all gathered errors are logged. If there is a fatal error * present in the list of errors an {@link ErrorMessagesException exception} is thrown. * * @param task task to be invoked. */ public static void processWithException(final Runnable task) { process(new Producer() { @Override public Void call() { task.run(); return null; } }, true); } private static T process(final Producer task, final boolean throwException) { try { return process((Callable) task, throwException); } catch (RuntimeException ex) { throw ex; } catch (Exception ex) { throw new RuntimeException(ex); } } private static T process(final Callable task, final boolean throwException) throws Exception { Errors instance = errors.get(); if (instance == null) { instance = new Errors(); errors.set(instance); } instance.preProcess(); Exception caught = null; try { return task.call(); } catch (Exception re) { // If a runtime exception is caught then report errors and rethrow. caught = re; } finally { instance.postProcess(throwException && caught == null); } throw caught; } private static Errors getInstance() { final Errors instance = errors.get(); // No error processing in scope if (instance == null) { throw new IllegalStateException(LocalizationMessages.NO_ERROR_PROCESSING_IN_SCOPE()); } // The following should not be necessary but given the fragile nature of // static thread local probably best to add it in case some internals of // this class change if (instance.stack == 0) { errors.remove(); throw new IllegalStateException(LocalizationMessages.NO_ERROR_PROCESSING_IN_SCOPE()); } return instance; } /** * Get the list of all error messages. * * @return non-null error message list. */ public static List getErrorMessages() { return getErrorMessages(false); } /** * Get the list of error messages. *

* The {@code afterMark} flag indicates whether only those issues should be returned that were * added after a {@link #mark() mark has been set}. *

* * @param afterMark if {@code true}, only issues added after a mark has been set are returned, * if {@code false} all issues are returned. * @return non-null error list. */ public static List getErrorMessages(final boolean afterMark) { return getInstance()._getErrorMessages(afterMark); } /** * Set a mark at a current position in the errors messages list. */ public static void mark() { getInstance()._mark(); } /** * Remove a previously set mark, if any. */ public static void unmark() { getInstance()._unmark(); } /** * Removes all issues that have been added since the last marked position as well as * removes the last mark. */ public static void reset() { getInstance()._reset(); } private final ArrayList issues = new ArrayList(0); private Errors() { } private Deque mark = new ArrayDeque(4); private int stack = 0; private void _mark() { mark.addLast(issues.size()); } private void _unmark() { mark.pollLast(); } private void _reset() { final Integer _pos = mark.pollLast(); // also performs "unmark" functionality final int markedPos = (_pos == null) ? -1 : _pos; if (markedPos >= 0 && markedPos < issues.size()) { issues.subList(markedPos, issues.size()).clear(); } } private void preProcess() { stack++; } private void postProcess(boolean throwException) { stack--; if (stack == 0) { try { if (!issues.isEmpty()) { processErrors(throwException); } } finally { errors.remove(); } } } private List _getErrorMessages(final boolean afterMark) { if (afterMark) { final Integer _pos = mark.peekLast(); final int markedPos = (_pos == null) ? -1 : _pos; if (markedPos >= 0 && markedPos < issues.size()) { return Collections.unmodifiableList(new ArrayList(issues.subList(markedPos, issues.size()))); } // else return all errors } return Collections.unmodifiableList(new ArrayList(issues)); } /** * Error message exception. */ public static class ErrorMessagesException extends RuntimeException { private final List messages; private ErrorMessagesException(final List messages) { this.messages = messages; } /** * Get encountered error messages. * * @return encountered error messages. */ public List getMessages() { return messages; } } /** * Generic error message. */ public static class ErrorMessage { private final Object source; private final String message; private final Severity severity; private ErrorMessage(final Object source, final String message, Severity severity) { this.source = source; this.message = message; this.severity = severity; } /** * Get {@link Severity}. * * @return severity of current {@code ErrorMessage}. */ public Severity getSeverity() { return severity; } /** * Human-readable description of the issue. * * @return message describing the issue. */ public String getMessage() { return message; } /** * The issue source. *

* Identifies the object where the issue was found. * * @return source of the issue. */ public Object getSource() { return source; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } ErrorMessage that = (ErrorMessage) o; if (message != null ? !message.equals(that.message) : that.message != null) { return false; } if (severity != that.severity) { return false; } if (source != null ? !source.equals(that.source) : that.source != null) { return false; } return true; } @Override public int hashCode() { int result = source != null ? source.hashCode() : 0; result = 31 * result + (message != null ? message.hashCode() : 0); result = 31 * result + (severity != null ? severity.hashCode() : 0); return result; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy