Lifecycles.java :  » Google-tech » warp-persist » com » wideplay » warp » persist » internal » Java Open Source

Java Open Source » Google tech » warp persist 
warp persist » com » wideplay » warp » persist » internal » Lifecycles.java
/**
 * Copyright (C) 2008 Wideplay Interactive.
 *
 * 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.wideplay.warp.persist.internal;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.List;

public class Lifecycles {
    private Lifecycles() {}

    public static <E extends Exception> void failEarlyAndLeaveNoOneBehind(List<Lifecycle> lifecycles, ExceptionalRunnable<E> exceptionalRunnable) throws E {
        failEarly(lifecycles);
        try {
            exceptionalRunnable.run();
        } finally {
            leaveNoOneBehind(lifecycles);
        }
    }

    public static void failEarly(List<Lifecycle> lifecycles) {
        // Iterate with index so we can clean up if needed.
        for (int i = 0, size = lifecycles.size(); i < size; i++) {
            try {
                lifecycles.get(i).start();
            } catch (RuntimeException e) {
                // clean up what we did so far and end this madness.
                try {
                    leaveNoOneBehind(lifecycles.subList(0, i));
                } catch (final RuntimeException closeErrors) {
                    // Better than nothing.
                    throw new MessageDelegatingRuntimeException(closeErrors.getMessage(), e);
                }
                throw e;
            }
        }
    }

    /**
     * Tries to end work for as much work as possible, in order.
     * Accumulates exceptions and rethrows them in a RuntimeException.
     */
    public static void leaveNoOneBehind(List<Lifecycle> lifecycles) {
        StringBuilder exceptionMessages = new StringBuilder();
        for (Lifecycle lifecycle : lifecycles) {
            try {
                lifecycle.stop();
            } catch (RuntimeException e) {
                // record the exception and proceed
                exceptionMessages.append(String.format("Could not end work for '%s': %s%n%s%n",
                        lifecycle.toString(), e.getMessage(), stackTraceAsString(e)));
            }
        }
        if (exceptionMessages.length() > 0) {
            throw new RuntimeException(exceptionMessages.toString());
        }
    }

    private static String stackTraceAsString(Exception e) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        try {
            e.printStackTrace(pw);
            return sw.getBuffer().toString();
        } finally {
            try {
                sw.close();
            } catch (IOException ignored) {
            } finally {
                pw.close();
            }
        }
    }

    // Static class because a generic class can't create a anonymous subclass of Throwable
    private static class MessageDelegatingRuntimeException extends RuntimeException {
        private final String newMessage;

        public MessageDelegatingRuntimeException(String newMessage, Throwable nestedThrowable) {
            super(nestedThrowable);
            this.newMessage = newMessage;
        }

        @Override
        public String getMessage() {
            return String.format("Unable to start work: %s%nUnable to clean up after failing:%n%s",
                    super.getMessage(), newMessage);
        }
    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.