001/* 002 * Extra Bnd Repository Plugins 003 * Copyright (C) 2019 Michael N. Lipp 004 * 005 * This program is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU Affero General Public License as published by 007 * the Free Software Foundation; either version 3 of the License, or 008 * (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, but 011 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 012 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License 013 * for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License along 016 * with this program; if not, see <http://www.gnu.org/licenses/>. 017 */ 018 019package de.mnl.osgi.bnd.maven; 020 021import java.lang.reflect.UndeclaredThrowableException; 022import java.util.concurrent.Callable; 023import java.util.regex.Pattern; 024import java.util.stream.Stream; 025 026/** 027 * The Class Utils. 028 */ 029public final class RepositoryUtils { 030 031 /** The Constant LIST_ITEM_SEPARATOR. */ 032 public static final Pattern LIST_ITEM_SEPARATOR 033 = Pattern.compile("\\s*,\\s*"); 034 035 private RepositoryUtils() { 036 } 037 038 /** 039 * Itemize list. 040 * 041 * @param list the list 042 * @return the stream 043 */ 044 public static Stream<String> itemizeList(String list) { 045 if (list == null) { 046 return Stream.empty(); 047 } 048 return LIST_ITEM_SEPARATOR.splitAsStream(list); 049 } 050 051 /** 052 * Run ignoring any throwable. 053 * 054 * @param runnable the function to be executed 055 */ 056 @SuppressWarnings({ "PMD.AvoidCatchingThrowable", "PMD.EmptyCatchBlock", 057 "PMD.AvoidDuplicateLiterals" }) 058 public static void runIgnoring(ThrowingRunnable runnable) { 059 try { 060 runnable.run(); 061 } catch (Throwable t) { 062 // Ignored 063 } 064 } 065 066 /** 067 * Run ignoring any throwable. If an exception occurs, the 068 * fallback value is returned. 069 * 070 * @param <T> the return type 071 * @param callable the function to be executed 072 * @param fallback the fallback value 073 * @return the t 074 */ 075 @SuppressWarnings({ "PMD.AvoidCatchingThrowable", "PMD.EmptyCatchBlock" }) 076 public static <T> T runIgnoring(Callable<T> callable, T fallback) { 077 try { 078 return callable.call(); 079 } catch (Throwable t) { 080 return fallback; 081 } 082 } 083 084 /** 085 * A runnable that may throw an exception. 086 */ 087 @FunctionalInterface 088 public interface ThrowingRunnable { 089 090 /** 091 * The operation to run. 092 * 093 * @throws Exception the exception 094 */ 095 @SuppressWarnings("PMD.SignatureDeclareThrowsException") 096 void run() throws Exception; 097 } 098 099 /** 100 * Converts any exception thrown by the supplier to an 101 * {@link UndeclaredThrowableException}. 102 * 103 * @param <T> the return value 104 * @param supplier the supplier 105 * @return the t 106 */ 107 @SuppressWarnings({ "PMD.AvoidCatchingThrowable", 108 "PMD.AvoidCatchingGenericException", "PMD.AvoidRethrowingException", 109 "PMD.AvoidDuplicateLiterals" }) 110 public static <T> T unthrow(Callable<T> supplier) { 111 try { 112 return supplier.call(); 113 } catch (RuntimeException e) { 114 throw e; 115 } catch (Throwable t) { 116 throw new UndeclaredThrowableException(t); 117 } 118 } 119 120 /** 121 * Converts any exception thrown by the runnable to an 122 * {@link UndeclaredThrowableException}. 123 * 124 * @param runnable the runnable 125 */ 126 @SuppressWarnings({ "PMD.AvoidCatchingGenericException", 127 "PMD.AvoidRethrowingException", "PMD.AvoidCatchingThrowable" }) 128 public static void unthrow(ThrowingRunnable runnable) { 129 try { 130 runnable.run(); 131 } catch (RuntimeException e) { 132 throw e; 133 } catch (Throwable t) { 134 throw new UndeclaredThrowableException(t); 135 } 136 } 137 138 /** 139 * Catches {@link UndeclaredThrowableException}s and unwraps 140 * any underlying exception of the given type. 141 * 142 * @param <T> the return type 143 * @param <E> the type of exception that is unwrapped 144 * @param rethrown the type of exception that is rethrown 145 * @param supplier the supplier 146 * @return the result from invoking the {@code supplier} 147 * @throws E the exception type 148 */ 149 @SuppressWarnings({ "unchecked", "PMD.AvoidCatchingGenericException", 150 "PMD.AvoidRethrowingException" }) 151 public static <T, E extends Throwable> T rethrow(Class<E> rethrown, 152 Callable<T> supplier) throws E { 153 try { 154 return supplier.call(); 155 } catch (UndeclaredThrowableException e) { 156 if (rethrown 157 .isAssignableFrom(e.getUndeclaredThrowable().getClass())) { 158 throw (E) e.getUndeclaredThrowable(); 159 } 160 throw e; 161 } catch (RuntimeException e) { 162 throw e; 163 } catch (Exception e) { 164 throw new UndeclaredThrowableException(e); 165 } 166 } 167 168 /** 169 * Catches {@link UndeclaredThrowableException}s and unwraps 170 * any underlying exception of the given type. 171 * 172 * @param <T> the return type 173 * @param <E1> the first exception type 174 * @param <E2> the second exception type 175 * @param rethrown1 the class of the first rethrown exception type 176 * @param rethrown2 the class of the second rethrown exception type 177 * @param function the function to be executed 178 * @return the result from invoking the {@code supplier} 179 * @throws E1 the e1 180 * @throws E2 the e2 181 */ 182 @SuppressWarnings({ "unchecked", "PMD.AvoidCatchingGenericException", 183 "PMD.AvoidRethrowingException" }) 184 public static <T, E1 extends Throwable, E2 extends Throwable> T 185 rethrow(Class<E1> rethrown1, Class<E2> rethrown2, 186 Callable<T> function) throws E1, E2 { 187 try { 188 return function.call(); 189 } catch (UndeclaredThrowableException e) { 190 if (rethrown1 191 .isAssignableFrom(e.getUndeclaredThrowable().getClass())) { 192 throw (E1) e.getUndeclaredThrowable(); 193 } 194 if (rethrown2 195 .isAssignableFrom(e.getUndeclaredThrowable().getClass())) { 196 throw (E2) e.getUndeclaredThrowable(); 197 } 198 throw e; 199 } catch (RuntimeException e) { 200 throw e; 201 } catch (Exception e) { 202 throw new UndeclaredThrowableException(e); 203 } 204 } 205 206 /** 207 * Catches {@link UndeclaredThrowableException}s and unwraps 208 * any underlying exception of the given type. 209 * 210 * @param <E> the type of exception that is unwrapped 211 * @param rethrown the type of exception that is rethrown 212 * @param runnable the runnable 213 * @throws E the exception type 214 */ 215 @SuppressWarnings({ "unchecked", "PMD.AvoidCatchingGenericException" }) 216 public static <E extends Throwable> void rethrow(Class<E> rethrown, 217 ThrowingRunnable runnable) throws E { 218 try { 219 runnable.run(); 220 } catch (UndeclaredThrowableException e) { 221 if (rethrown 222 .isAssignableFrom(e.getUndeclaredThrowable().getClass())) { 223 throw (E) e.getUndeclaredThrowable(); 224 } 225 throw e; 226 } catch (Exception e) { 227 throw new UndeclaredThrowableException(e); 228 } 229 } 230}