001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.camel.util;
018
019import java.util.ArrayList;
020import java.util.Collections;
021import java.util.List;
022
023import org.apache.camel.Exchange;
024import org.apache.camel.Route;
025import org.apache.camel.spi.Synchronization;
026import org.apache.camel.spi.SynchronizationRouteAware;
027import org.apache.camel.spi.UnitOfWork;
028import org.slf4j.Logger;
029import org.slf4j.LoggerFactory;
030
031/**
032 * Utility methods for {@link org.apache.camel.spi.UnitOfWork}
033 *
034 * @version 
035 */
036public final class UnitOfWorkHelper {
037
038    private static final Logger LOG = LoggerFactory.getLogger(UnitOfWorkHelper.class);
039
040    private UnitOfWorkHelper() {
041    }
042
043    /**
044     * Creates a new {@link UnitOfWork}.
045     *
046     * @param exchange the exchange
047     * @return the created unit of work (is not started)
048     * @deprecated use {@link org.apache.camel.CamelContext#getUnitOfWorkFactory()} instead.
049     */
050    @Deprecated
051    public static UnitOfWork createUoW(Exchange exchange) {
052        return exchange.getContext().getUnitOfWorkFactory().createUnitOfWork(exchange);
053    }
054
055    /**
056     * Done and stop the {@link UnitOfWork}.
057     *
058     * @param uow the unit of work
059     * @param exchange the exchange (will unset the UoW on the exchange)
060     */
061    public static void doneUow(UnitOfWork uow, Exchange exchange) {
062        // unit of work is done
063        try {
064            if (uow != null) {
065                uow.done(exchange);
066            }
067        } catch (Throwable e) {
068            LOG.warn("Exception occurred during done UnitOfWork for Exchange: " + exchange
069                    + ". This exception will be ignored.", e);
070        }
071        try {
072            if (uow != null) {
073                uow.stop();
074            }
075        } catch (Throwable e) {
076            LOG.warn("Exception occurred during stopping UnitOfWork for Exchange: " + exchange
077                    + ". This exception will be ignored.", e);
078        }
079
080        // remove uow from exchange as its done
081        exchange.setUnitOfWork(null);
082    }
083
084    public static void doneSynchronizations(Exchange exchange, List<Synchronization> synchronizations, Logger log) {
085        boolean failed = exchange.isFailed();
086
087        if (synchronizations != null && !synchronizations.isEmpty()) {
088            // work on a copy of the list to avoid any modification which may cause ConcurrentModificationException
089            List<Synchronization> copy = new ArrayList<>(synchronizations);
090
091            // reverse so we invoke it FILO style instead of FIFO
092            Collections.reverse(copy);
093            // and honor if any was ordered by sorting it accordingly
094            copy.sort(OrderedComparator.get());
095
096            // invoke synchronization callbacks
097            for (Synchronization synchronization : copy) {
098                try {
099                    if (failed) {
100                        log.trace("Invoking synchronization.onFailure: {} with {}", synchronization, exchange);
101                        synchronization.onFailure(exchange);
102                    } else {
103                        log.trace("Invoking synchronization.onComplete: {} with {}", synchronization, exchange);
104                        synchronization.onComplete(exchange);
105                    }
106                } catch (Throwable e) {
107                    // must catch exceptions to ensure all synchronizations have a chance to run
108                    log.warn("Exception occurred during onCompletion. This exception will be ignored.", e);
109                }
110            }
111        }
112    }
113
114    public static void beforeRouteSynchronizations(Route route, Exchange exchange, List<Synchronization> synchronizations, Logger log) {
115        if (synchronizations != null && !synchronizations.isEmpty()) {
116            // work on a copy of the list to avoid any modification which may cause ConcurrentModificationException
117            List<Synchronization> copy = new ArrayList<>(synchronizations);
118
119            // reverse so we invoke it FILO style instead of FIFO
120            Collections.reverse(copy);
121            // and honor if any was ordered by sorting it accordingly
122            copy.sort(OrderedComparator.get());
123
124            // invoke synchronization callbacks
125            for (Synchronization synchronization : copy) {
126                if (synchronization instanceof SynchronizationRouteAware) {
127                    try {
128                        log.trace("Invoking synchronization.onBeforeRoute: {} with {}", synchronization, exchange);
129                        ((SynchronizationRouteAware) synchronization).onBeforeRoute(route, exchange);
130                    } catch (Throwable e) {
131                        // must catch exceptions to ensure all synchronizations have a chance to run
132                        log.warn("Exception occurred during onBeforeRoute. This exception will be ignored.", e);
133                    }
134                }
135            }
136        }
137    }
138
139    public static void afterRouteSynchronizations(Route route, Exchange exchange, List<Synchronization> synchronizations, Logger log) {
140        if (synchronizations != null && !synchronizations.isEmpty()) {
141            // work on a copy of the list to avoid any modification which may cause ConcurrentModificationException
142            List<Synchronization> copy = new ArrayList<>(synchronizations);
143
144            // reverse so we invoke it FILO style instead of FIFO
145            Collections.reverse(copy);
146            // and honor if any was ordered by sorting it accordingly
147            copy.sort(OrderedComparator.get());
148
149            // invoke synchronization callbacks
150            for (Synchronization synchronization : copy) {
151                if (synchronization instanceof SynchronizationRouteAware) {
152                    try {
153                        log.trace("Invoking synchronization.onAfterRoute: {} with {}", synchronization, exchange);
154                        ((SynchronizationRouteAware) synchronization).onAfterRoute(route, exchange);
155                    } catch (Throwable e) {
156                        // must catch exceptions to ensure all synchronizations have a chance to run
157                        log.warn("Exception occurred during onAfterRoute. This exception will be ignored.", e);
158                    }
159                }
160            }
161        }
162    }
163
164}