http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/brooklyn/test/Asserts.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/brooklyn/test/Asserts.java b/utils/common/src/main/java/brooklyn/test/Asserts.java deleted file mode 100644 index b3c1e01..0000000 --- a/utils/common/src/main/java/brooklyn/test/Asserts.java +++ /dev/null @@ -1,499 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 brooklyn.test; - -import groovy.lang.Closure; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Enumeration; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicReference; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import brooklyn.util.collections.MutableSet; -import brooklyn.util.exceptions.Exceptions; -import brooklyn.util.time.Duration; - -import com.google.common.annotations.Beta; -import com.google.common.base.Predicate; -import com.google.common.base.Predicates; -import com.google.common.base.Supplier; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; - -/** - * TODO should move this to new package brooklyn.util.assertions - * and TODO should add a repeating() method which returns an AssertingRepeater extending Repeater - * and: - * <li> adds support for requireAllIterationsTrue - * <li> convenience run methods equivalent to succeedsEventually and succeedsContinually - */ -@Beta -public class Asserts { - - /** - * The default timeout for assertions. Alter in individual tests by giving a - * "timeout" entry in method flags. - */ - public static final Duration DEFAULT_TIMEOUT = Duration.THIRTY_SECONDS; - - private static final Logger log = LoggerFactory.getLogger(Asserts.class); - - private Asserts() {} - - // --- selected routines from testng.Assert for visibility without needing that package - - /** - * Asserts that a condition is true. If it isn't, - * an AssertionError, with the given message, is thrown. - * @param condition the condition to evaluate - * @param message the assertion error message - */ - public static void assertTrue(boolean condition, String message) { - if (!condition) fail(message); - } - - /** - * Asserts that a condition is false. If it isn't, - * an AssertionError, with the given message, is thrown. - * @param condition the condition to evaluate - * @param message the assertion error message - */ - public static void assertFalse(boolean condition, String message) { - if (condition) fail(message); - } - - /** - * Fails a test with the given message. - * @param message the assertion error message - */ - public static AssertionError fail(String message) { - throw new AssertionError(message); - } - - public static void assertEqualsIgnoringOrder(Iterable<?> actual, Iterable<?> expected) { - assertEqualsIgnoringOrder(actual, expected, false, null); - } - - public static void assertEqualsIgnoringOrder(Iterable<?> actual, Iterable<?> expected, boolean logDuplicates, String errmsg) { - Set<?> actualSet = Sets.newLinkedHashSet(actual); - Set<?> expectedSet = Sets.newLinkedHashSet(expected); - Set<?> extras = Sets.difference(actualSet, expectedSet); - Set<?> missing = Sets.difference(expectedSet, actualSet); - List<Object> duplicates = Lists.newArrayList(actual); - for (Object a : actualSet) { - duplicates.remove(a); - } - String fullErrmsg = "extras="+extras+"; missing="+missing - + (logDuplicates ? "; duplicates="+MutableSet.copyOf(duplicates) : "") - +"; actualSize="+Iterables.size(actual)+"; expectedSize="+Iterables.size(expected) - +"; actual="+actual+"; expected="+expected+"; "+errmsg; - assertTrue(extras.isEmpty(), fullErrmsg); - assertTrue(missing.isEmpty(), fullErrmsg); - assertTrue(Iterables.size(actual) == Iterables.size(expected), fullErrmsg); - assertTrue(actualSet.equals(expectedSet), fullErrmsg); // should be covered by extras/missing/size test - } - - // --- new routines - - public static <T> void eventually(Supplier<? extends T> supplier, Predicate<T> predicate) { - eventually(ImmutableMap.<String,Object>of(), supplier, predicate); - } - - public static <T> void eventually(Map<String,?> flags, Supplier<? extends T> supplier, Predicate<T> predicate) { - eventually(flags, supplier, predicate, (String)null); - } - - public static <T> void eventually(Map<String,?> flags, Supplier<? extends T> supplier, Predicate<T> predicate, String errMsg) { - Duration timeout = toDuration(flags.get("timeout"), Duration.ONE_SECOND); - Duration period = toDuration(flags.get("period"), Duration.millis(10)); - long periodMs = period.toMilliseconds(); - long startTime = System.currentTimeMillis(); - long expireTime = startTime+timeout.toMilliseconds(); - - boolean first = true; - T supplied = supplier.get(); - while (first || System.currentTimeMillis() <= expireTime) { - supplied = supplier.get(); - if (predicate.apply(supplied)) { - return; - } - first = false; - if (periodMs > 0) sleep(periodMs); - } - fail("supplied="+supplied+"; predicate="+predicate+(errMsg!=null?"; "+errMsg:"")); - } - - // TODO improve here -- these methods aren't very useful without timeouts - public static <T> void continually(Supplier<? extends T> supplier, Predicate<T> predicate) { - continually(ImmutableMap.<String,Object>of(), supplier, predicate); - } - - public static <T> void continually(Map<String,?> flags, Supplier<? extends T> supplier, Predicate<? super T> predicate) { - continually(flags, supplier, predicate, (String)null); - } - - public static <T> void continually(Map<String,?> flags, Supplier<? extends T> supplier, Predicate<T> predicate, String errMsg) { - Duration duration = toDuration(flags.get("timeout"), Duration.ONE_SECOND); - Duration period = toDuration(flags.get("period"), Duration.millis(10)); - long periodMs = period.toMilliseconds(); - long startTime = System.currentTimeMillis(); - long expireTime = startTime+duration.toMilliseconds(); - - boolean first = true; - while (first || System.currentTimeMillis() <= expireTime) { - assertTrue(predicate.apply(supplier.get()), "supplied="+supplier.get()+"; predicate="+predicate+(errMsg!=null?"; "+errMsg:"")); - if (periodMs > 0) sleep(periodMs); - first = false; - } - } - - - /** - * Asserts given runnable succeeds in default duration. - * @see #DEFAULT_TIMEOUT - */ - public static void succeedsEventually(Runnable r) { - succeedsEventually(ImmutableMap.<String,Object>of(), r); - } - - public static void succeedsEventually(Map<String,?> flags, Runnable r) { - succeedsEventually(flags, toCallable(r)); - } - - /** - * Asserts given callable succeeds (runs without failure) in default duration. - * @see #DEFAULT_TIMEOUT - */ - public static <T> T succeedsEventually(Callable<T> c) { - return succeedsEventually(ImmutableMap.<String,Object>of(), c); - } - - // FIXME duplication with TestUtils.BooleanWithMessage - public static class BooleanWithMessage { - boolean value; String message; - public BooleanWithMessage(boolean value, String message) { - this.value = value; this.message = message; - } - public boolean asBoolean() { - return value; - } - public String toString() { - return message; - } - } - - /** - * Convenience method for cases where we need to test until something is true. - * - * The runnable will be invoked periodically until it succesfully concludes. - * <p> - * The following flags are supported: - * <ul> - * <li>abortOnError (boolean, default true) - * <li>abortOnException - (boolean, default false) - * <li>timeout - (a Duration or an integer in millis, defaults to 30*SECONDS) - * <li>period - (a Duration or an integer in millis, for fixed retry time; if not set, defaults to exponentially increasing from 1 to 500ms) - * <li>minPeriod - (a Duration or an integer in millis; only used if period not explicitly set; the minimum period when exponentially increasing; defaults to 1ms) - * <li>maxPeriod - (a Duration or an integer in millis; only used if period not explicitly set; the maximum period when exponentially increasing; defaults to 500ms) - * <li>maxAttempts - (integer, Integer.MAX_VALUE) - * </ul> - * - * The following flags are deprecated: - * <ul> - * <li>useGroovyTruth - (defaults to false; any result code apart from 'false' will be treated as success including null; ignored for Runnables which aren't Callables) - * </ul> - * - * @param flags, accepts the flags listed above - * @param r - * @param finallyBlock - */ - public static <T> T succeedsEventually(Map<String,?> flags, Callable<T> c) { - boolean abortOnException = get(flags, "abortOnException", false); - boolean abortOnError = get(flags, "abortOnError", false); - boolean useGroovyTruth = get(flags, "useGroovyTruth", false); - boolean logException = get(flags, "logException", true); - - // To speed up tests, default is for the period to start small and increase... - Duration duration = toDuration(flags.get("timeout"), DEFAULT_TIMEOUT); - Duration fixedPeriod = toDuration(flags.get("period"), null); - Duration minPeriod = (fixedPeriod != null) ? fixedPeriod : toDuration(flags.get("minPeriod"), Duration.millis(1)); - Duration maxPeriod = (fixedPeriod != null) ? fixedPeriod : toDuration(flags.get("maxPeriod"), Duration.millis(500)); - int maxAttempts = get(flags, "maxAttempts", Integer.MAX_VALUE); - int attempt = 0; - long startTime = System.currentTimeMillis(); - try { - Throwable lastException = null; - T result = null; - long lastAttemptTime = 0; - long expireTime = startTime+duration.toMilliseconds(); - long sleepTimeBetweenAttempts = minPeriod.toMilliseconds(); - - while (attempt < maxAttempts && lastAttemptTime < expireTime) { - try { - attempt++; - lastAttemptTime = System.currentTimeMillis(); - result = c.call(); - if (log.isTraceEnabled()) log.trace("Attempt {} after {} ms: {}", new Object[] {attempt, System.currentTimeMillis() - startTime, result}); - if (useGroovyTruth) { - if (groovyTruth(result)) return result; - } else if (Boolean.FALSE.equals(result)) { - if (result instanceof BooleanWithMessage) - log.warn("Test returned an instance of BooleanWithMessage but useGroovyTruth is not set! " + - "The result of this probably isn't what you intended."); - // FIXME surprising behaviour, "false" result here is acceptable - return result; - } else { - return result; - } - lastException = null; - } catch(Throwable e) { - lastException = e; - if (log.isTraceEnabled()) log.trace("Attempt {} after {} ms: {}", new Object[] {attempt, System.currentTimeMillis() - startTime, e.getMessage()}); - if (abortOnException) throw e; - if (abortOnError && e instanceof Error) throw e; - } - long sleepTime = Math.min(sleepTimeBetweenAttempts, expireTime-System.currentTimeMillis()); - if (sleepTime > 0) Thread.sleep(sleepTime); - sleepTimeBetweenAttempts = Math.min(sleepTimeBetweenAttempts*2, maxPeriod.toMilliseconds()); - } - - log.info("succeedsEventually exceeded max attempts or timeout - {} attempts lasting {} ms, for {}", new Object[] {attempt, System.currentTimeMillis()-startTime, c}); - if (lastException != null) - throw lastException; - throw fail("invalid result: "+result); - } catch (Throwable t) { - if (logException) log.info("failed succeeds-eventually, "+attempt+" attempts, "+ - (System.currentTimeMillis()-startTime)+"ms elapsed "+ - "(rethrowing): "+t); - throw propagate(t); - } - } - - public static <T> void succeedsContinually(Runnable r) { - succeedsContinually(ImmutableMap.<String,Object>of(), r); - } - - public static <T> void succeedsContinually(Map<?,?> flags, Runnable r) { - succeedsContinually(flags, toCallable(r)); - } - - public static <T> T succeedsContinually(Callable<T> c) { - return succeedsContinually(ImmutableMap.<String,Object>of(), c); - } - - public static <T> T succeedsContinually(Map<?,?> flags, Callable<T> job) { - Duration duration = toDuration(flags.get("timeout"), Duration.ONE_SECOND); - Duration period = toDuration(flags.get("period"), Duration.millis(10)); - long periodMs = period.toMilliseconds(); - long startTime = System.currentTimeMillis(); - long expireTime = startTime+duration.toMilliseconds(); - int attempt = 0; - - boolean first = true; - T result = null; - while (first || System.currentTimeMillis() <= expireTime) { - attempt++; - try { - result = job.call(); - } catch (Exception e) { - log.info("succeedsContinually failed - {} attempts lasting {} ms, for {} (rethrowing)", new Object[] {attempt, System.currentTimeMillis()-startTime, job}); - throw propagate(e); - } - if (periodMs > 0) sleep(periodMs); - first = false; - } - return result; - } - - private static Duration toDuration(Object duration, Duration defaultVal) { - if (duration == null) - return defaultVal; - else - return Duration.of(duration); - } - - public static void assertFails(Runnable r) { - assertFailsWith(toCallable(r), Predicates.alwaysTrue()); - } - - public static void assertFails(Callable<?> c) { - assertFailsWith(c, Predicates.alwaysTrue()); - } - - public static void assertFailsWith(Callable<?> c, final Closure<Boolean> exceptionChecker) { - assertFailsWith(c, new Predicate<Throwable>() { - public boolean apply(Throwable input) { - return exceptionChecker.call(input); - } - }); - } - - public static void assertFailsWith(Runnable c, final Class<? extends Throwable> validException, final Class<? extends Throwable> ...otherValidExceptions) { - final List<Class<?>> validExceptions = ImmutableList.<Class<?>>builder() - .add(validException) - .addAll(ImmutableList.copyOf(otherValidExceptions)) - .build(); - - assertFailsWith(c, new Predicate<Throwable>() { - public boolean apply(Throwable e) { - for (Class<?> validException: validExceptions) { - if (validException.isInstance(e)) return true; - } - fail("Test threw exception of unexpected type "+e.getClass()+"; expecting "+validExceptions); - return false; - } - }); - } - - public static void assertFailsWith(Runnable r, Predicate<? super Throwable> exceptionChecker) { - assertFailsWith(toCallable(r), exceptionChecker); - } - - public static void assertFailsWith(Callable<?> c, Predicate<? super Throwable> exceptionChecker) { - boolean failed = false; - try { - c.call(); - } catch (Throwable e) { - failed = true; - if (!exceptionChecker.apply(e)) { - log.debug("Test threw invalid exception (failing)", e); - fail("Test threw invalid exception: "+e); - } - log.debug("Test for exception successful ("+e+")"); - } - if (!failed) fail("Test code should have thrown exception but did not"); - } - - public static void assertReturnsEventually(final Runnable r, Duration timeout) throws InterruptedException, ExecutionException, TimeoutException { - final AtomicReference<Throwable> throwable = new AtomicReference<Throwable>(); - Runnable wrappedR = new Runnable() { - @Override public void run() { - try { - r.run(); - } catch (Throwable t) { - throwable.set(t); - throw Exceptions.propagate(t); - } - } - }; - Thread thread = new Thread(wrappedR, "assertReturnsEventually("+r+")"); - try { - thread.start(); - thread.join(timeout.toMilliseconds()); - if (thread.isAlive()) { - throw new TimeoutException("Still running: r="+r+"; thread="+Arrays.toString(thread.getStackTrace())); - } - } catch (InterruptedException e) { - throw Exceptions.propagate(e); - } finally { - thread.interrupt(); - } - - if (throwable.get() != null) { - throw new ExecutionException(throwable.get()); - } - } - - public static <T> void assertThat(T object, Predicate<T> condition) { - if (condition.apply(object)) return; - fail("Failed "+condition+": "+object); - } - - @SuppressWarnings("rawtypes") - private static boolean groovyTruth(Object o) { - // TODO Doesn't handle matchers (see http://docs.codehaus.org/display/GROOVY/Groovy+Truth) - if (o == null) { - return false; - } else if (o instanceof Boolean) { - return (Boolean)o; - } else if (o instanceof String) { - return !((String)o).isEmpty(); - } else if (o instanceof Collection) { - return !((Collection)o).isEmpty(); - } else if (o instanceof Map) { - return !((Map)o).isEmpty(); - } else if (o instanceof Iterator) { - return ((Iterator)o).hasNext(); - } else if (o instanceof Enumeration) { - return ((Enumeration)o).hasMoreElements(); - } else { - return true; - } - } - - @SuppressWarnings("unchecked") - private static <T> T get(Map<String,?> map, String key, T defaultVal) { - Object val = map.get(key); - return (T) ((val == null) ? defaultVal : val); - } - - private static Callable<?> toCallable(Runnable r) { - return (r instanceof Callable) ? (Callable<?>)r : new RunnableAdapter<Void>(r, null); - } - - /** Same as {@link java.util.concurrent.Executors#callable(Runnable)}, except includes toString() */ - static final class RunnableAdapter<T> implements Callable<T> { - final Runnable task; - final T result; - RunnableAdapter(Runnable task, T result) { - this.task = task; - this.result = result; - } - public T call() { - task.run(); - return result; - } - @Override - public String toString() { - return "RunnableAdapter("+task+")"; - } - } - - private static void sleep(long periodMs) { - if (periodMs > 0) { - try { - Thread.sleep(periodMs); - } catch (InterruptedException e) { - throw propagate(e); - } - } - } - - private static RuntimeException propagate(Throwable t) { - if (t instanceof InterruptedException) { - Thread.currentThread().interrupt(); - } - if (t instanceof RuntimeException) throw (RuntimeException)t; - if (t instanceof Error) throw (Error)t; - throw new RuntimeException(t); - } -}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/brooklyn/util/CommandLineUtil.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/brooklyn/util/CommandLineUtil.java b/utils/common/src/main/java/brooklyn/util/CommandLineUtil.java deleted file mode 100644 index 6ccdc2f..0000000 --- a/utils/common/src/main/java/brooklyn/util/CommandLineUtil.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 brooklyn.util; - -import java.util.List; - -// FIXME move to brooklyn.util.cli.CommandLineArgs, and change get to "remove" -public class CommandLineUtil { - - public static String getCommandLineOption (List<String> args, String param){ - return getCommandLineOption(args, param, null); - } - - /** given a list of args, e.g. --name Foo --parent Bob - * will return "Foo" as param name, and remove those entries from the args list - */ - public static String getCommandLineOption(List<String> args, String param, String defaultValue) { - int i = args.indexOf(param); - if (i >= 0) { - String result = args.get(i + 1); - args.remove(i + 1); - args.remove(i); - return result; - } else { - return defaultValue; - } - } - - public static int getCommandLineOptionInt(List<String> args, String param, int defaultValue) { - String s = getCommandLineOption(args, param,null); - if (s == null) return defaultValue; - return Integer.parseInt(s); - } - - //we don't want instances. - private CommandLineUtil(){} -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/brooklyn/util/JavaGroovyEquivalents.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/brooklyn/util/JavaGroovyEquivalents.java b/utils/common/src/main/java/brooklyn/util/JavaGroovyEquivalents.java deleted file mode 100644 index 293cd7b..0000000 --- a/utils/common/src/main/java/brooklyn/util/JavaGroovyEquivalents.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 brooklyn.util; - -import groovy.lang.Closure; -import groovy.lang.GString; -import groovy.time.TimeDuration; - -import java.util.Collection; -import java.util.Enumeration; -import java.util.Iterator; -import java.util.Map; -import java.util.concurrent.Callable; -import java.util.concurrent.Executors; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import brooklyn.util.time.Duration; - -import com.google.common.base.Function; -import com.google.common.base.Predicate; -import com.google.common.collect.Iterables; -import com.google.common.collect.Maps; - -// FIXME move to brooklyn.util.groovy -public class JavaGroovyEquivalents { - - private static final Logger log = LoggerFactory.getLogger(JavaGroovyEquivalents.class); - - public static String join(Collection<?> collection, String separator) { - StringBuffer result = new StringBuffer(); - Iterator<?> ci = collection.iterator(); - if (ci.hasNext()) result.append(asNonnullString(ci.next())); - while (ci.hasNext()) { - result.append(separator); - result.append(asNonnullString(ci.next())); - } - return result.toString(); - } - - /** simple elvislike operators; uses groovy truth */ - @SuppressWarnings("unchecked") - public static <T> Collection<T> elvis(Collection<T> preferred, Collection<?> fallback) { - // TODO Would be nice to not cast, but this is groovy equivalent! Let's fix generics in stage 2 - return groovyTruth(preferred) ? preferred : (Collection<T>) fallback; - } - public static String elvis(String preferred, String fallback) { - return groovyTruth(preferred) ? preferred : fallback; - } - public static String elvisString(Object preferred, Object fallback) { - return elvis(asString(preferred), asString(fallback)); - } - public static <T> T elvis(T preferred, T fallback) { - return groovyTruth(preferred) ? preferred : fallback; - } - public static <T> T elvis(Iterable<?> preferences) { - return elvis(Iterables.toArray(preferences, Object.class)); - } - public static <T> T elvis(Object... preferences) { - if (preferences.length == 0) throw new IllegalArgumentException("preferences must not be empty for elvis"); - for (Object contender : preferences) { - if (groovyTruth(contender)) return (T) fix(contender); - } - return (T) fix(preferences[preferences.length-1]); - } - - public static Object fix(Object o) { - if (o instanceof GString) return (o.toString()); - return o; - } - - public static String asString(Object o) { - if (o==null) return null; - return o.toString(); - } - public static String asNonnullString(Object o) { - if (o==null) return "null"; - return o.toString(); - } - - public static boolean groovyTruth(Collection<?> c) { - return c != null && !c.isEmpty(); - } - public static boolean groovyTruth(String s) { - return s != null && !s.isEmpty(); - } - public static boolean groovyTruth(Object o) { - // TODO Doesn't handle matchers (see http://docs.codehaus.org/display/GROOVY/Groovy+Truth) - if (o == null) { - return false; - } else if (o instanceof Boolean) { - return (Boolean)o; - } else if (o instanceof String) { - return !((String)o).isEmpty(); - } else if (o instanceof Collection) { - return !((Collection)o).isEmpty(); - } else if (o instanceof Map) { - return !((Map)o).isEmpty(); - } else if (o instanceof Iterator) { - return ((Iterator)o).hasNext(); - } else if (o instanceof Enumeration) { - return ((Enumeration)o).hasMoreElements(); - } else { - return true; - } - } - - public static <T> Predicate<T> groovyTruthPredicate() { - return new Predicate<T>() { - @Override public boolean apply(T val) { - return groovyTruth(val); - } - }; - } - - public static Function<Object,Boolean> groovyTruthFunction() { - return new Function<Object, Boolean>() { - @Override public Boolean apply(Object input) { - return groovyTruth(input); - } - }; - } - - public static <K,V> Map<K,V> mapOf(K key1, V val1) { - Map<K,V> result = Maps.newLinkedHashMap(); - result.put(key1, val1); - return result; - } - - /** @deprecated since 0.6.0 use {@link Duration#of(Object)} */ - @Deprecated - public static TimeDuration toTimeDuration(Object duration) { - // TODO Lazy coding here for large number values; but refactoring away from groovy anyway... - - if (duration == null) { - return null; - } else if (duration instanceof TimeDuration) { - return (TimeDuration) duration; - } else if (duration instanceof Number) { - long d = ((Number)duration).longValue(); - if (d <= Integer.MAX_VALUE && d >= Integer.MIN_VALUE) { - return new TimeDuration(0,0,0,(int)d); - } else { - log.warn("Number "+d+" too large to convert to TimeDuration; using Integer.MAX_VALUE instead"); - return new TimeDuration(0,0,0,Integer.MAX_VALUE); - } - } else { - throw new IllegalArgumentException("Cannot convert "+duration+" of type "+duration.getClass().getName()+" to a TimeDuration"); - } - } - - public static <T> Predicate<T> toPredicate(final Closure<Boolean> c) { - return new Predicate<T>() { - @Override public boolean apply(T input) { - return c.call(input); - } - }; - } - - @SuppressWarnings("unchecked") - public static <T> Callable<T> toCallable(final Runnable job) { - return (Callable<T>) ((job instanceof Callable) ? (Callable<T>)job : Executors.callable(job)); - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/brooklyn/util/ShellUtils.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/brooklyn/util/ShellUtils.java b/utils/common/src/main/java/brooklyn/util/ShellUtils.java deleted file mode 100644 index 2c53f93..0000000 --- a/utils/common/src/main/java/brooklyn/util/ShellUtils.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 brooklyn.util; - -import groovy.io.GroovyPrintStream; -import groovy.time.TimeDuration; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.PrintStream; -import java.util.Map; -import java.util.concurrent.atomic.AtomicBoolean; - -import org.slf4j.Logger; - -import brooklyn.util.exceptions.Exceptions; -import brooklyn.util.stream.StreamGobbler; -import brooklyn.util.stream.Streams; -import brooklyn.util.text.Strings; - -import com.google.common.collect.Maps; -import com.google.common.io.Closer; - -/** - * @deprecated since 0.7; does not return exit status, stderr, etc, so utility is of very limited use; and is not used in core brooklyn at all!; - * use ProcessTool or SystemProcessTaskFactory. - */ -@Deprecated -public class ShellUtils { - - public static long TIMEOUT = 60*1000; - - /** - * Executes the given command. - * <p> - * Uses {@code bash -l -c cmd} (to have a good PATH set), and defaults for other fields. - * <p> - * requires a logger and a context object (whose toString is used in the logger and in error messages) - * optionally takes a string to use as input to the command - * - * @see {@link #exec(String, String, Logger, Object)} - */ - public static String[] exec(String cmd, Logger log, Object context) { - return exec(cmd, null, log, context); - } - /** @see {@link #exec(String[], String[], File, String, Logger, Object)} */ - public static String[] exec(String cmd, String input, Logger log, Object context) { - return exec(new String[] { "bash", "-l", "-c", cmd }, null, null, input, log, context); - } - /** @see {@link #exec(Map, String[], String[], File, String, Logger, Object)} */ - public static String[] exec(Map flags, String cmd, Logger log, Object context) { - return exec(flags, new String[] { "bash", "-l", "-c", cmd }, null, null, null, log, context); - } - /** @see {@link #exec(Map, String[], String[], File, String, Logger, Object)} */ - public static String[] exec(Map flags, String cmd, String input, Logger log, Object context) { - return exec(flags, new String[] { "bash", "-l", "-c", cmd }, null, null, input, log, context); - } - /** @see {@link #exec(Map, String[], String[], File, String, Logger, Object)} */ - public static String[] exec(String[] cmd, String[] envp, File dir, String input, Logger log, Object context) { - return exec(Maps.newLinkedHashMap(), cmd, envp, dir, input, log, context); - } - - private static long getTimeoutMs(Map flags) { - long timeout = TIMEOUT; - - Object tf = flags.get("timeout"); - - if (tf instanceof Number) { - timeout = ((Number) tf).longValue(); - } else if (tf instanceof TimeDuration) { - timeout = ((TimeDuration) tf).toMilliseconds(); - } - - //if (tf != null) timeout = tf; - - return timeout; - } - - /** - * Executes the given command. - * <p> - * Uses the given environmnet (inherited if null) and cwd ({@literal .} if null), - * feeding it the given input stream (if not null) and logging I/O at debug (if not null). - * <p> - * flags: timeout (Duration), 0 for forever; default 60 seconds - * - * @throws IllegalStateException if return code non-zero - * @return lines from stdout. - */ - public static String[] exec(Map flags, final String[] cmd, String[] envp, File dir, String input, final Logger log, final Object context) { - if (log.isDebugEnabled()) { - log.debug("Running local command: {}% {}", context, Strings.join(cmd, " ")); - } - Closer closer = Closer.create(); - try { - final Process proc = Runtime.getRuntime().exec(cmd, envp, dir); // Call *execute* on the string - ByteArrayOutputStream stdoutB = new ByteArrayOutputStream(); - ByteArrayOutputStream stderrB = new ByteArrayOutputStream(); - PrintStream stdoutP = new GroovyPrintStream(stdoutB); - PrintStream stderrP = new GroovyPrintStream(stderrB); - @SuppressWarnings("resource") - StreamGobbler stdoutG = new StreamGobbler(proc.getInputStream(), stdoutP, log).setLogPrefix("["+context+":stdout] "); - stdoutG.start(); - closer.register(stdoutG); - @SuppressWarnings("resource") - StreamGobbler stderrG = new StreamGobbler(proc.getErrorStream(), stderrP, log).setLogPrefix("["+context+":stderr] "); - stderrG.start(); - closer.register(stderrG); - if (input!=null && input.length()>0) { - proc.getOutputStream().write(input.getBytes()); - proc.getOutputStream().flush(); - } - - final long timeout = getTimeoutMs(flags); - final AtomicBoolean ended = new AtomicBoolean(false); - final AtomicBoolean killed = new AtomicBoolean(false); - - //if a timeout was specified, this thread will kill the process. This is a work around because the process.waitFor' - //doesn't accept a timeout. - Thread timeoutThread = new Thread(new Runnable() { - public void run() { - if (timeout <= 0) return; - try { - Thread.sleep(timeout); - if (!ended.get()) { - if (log.isDebugEnabled()) { - log.debug("Timeout exceeded for "+context+"% "+Strings.join(cmd, " ")); - } - proc.destroy(); - killed.set(true); - } - } catch (Exception e) { } - } - }); - if (timeout > 0) timeoutThread.start(); - int exitCode = proc.waitFor(); - ended.set(true); - if (timeout > 0) timeoutThread.interrupt(); - - stdoutG.blockUntilFinished(); - stderrG.blockUntilFinished(); - if (exitCode!=0 || killed.get()) { - String message = killed.get() ? "terminated after timeout" : "exit code "+exitCode; - if (log.isDebugEnabled()) { - log.debug("Completed local command (problem, throwing): "+context+"% "+Strings.join(cmd, " ")+" - "+message); - } - String e = "Command failed ("+message+"): "+Strings.join(cmd, " "); - log.warn(e+"\n"+stdoutB+(stderrB.size()>0 ? "\n--\n"+stderrB : "")); - throw new IllegalStateException(e+" (details logged)"); - } - if (log.isDebugEnabled()) { - log.debug("Completed local command: "+context+"% "+Strings.join(cmd, " ")+" - exit code 0"); - } - return stdoutB.toString().split("\n"); - } catch (IOException e) { - throw Exceptions.propagate(e); - } catch (InterruptedException e) { - throw Exceptions.propagate(e); - } finally { - Streams.closeQuietly(closer); - } - } - -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/brooklyn/util/collections/CollectionFunctionals.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/brooklyn/util/collections/CollectionFunctionals.java b/utils/common/src/main/java/brooklyn/util/collections/CollectionFunctionals.java deleted file mode 100644 index 2d08bd2..0000000 --- a/utils/common/src/main/java/brooklyn/util/collections/CollectionFunctionals.java +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 brooklyn.util.collections; - -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.annotation.Nullable; - -import brooklyn.util.collections.QuorumCheck.QuorumChecks; - -import com.google.common.base.Function; -import com.google.common.base.Functions; -import com.google.common.base.Preconditions; -import com.google.common.base.Predicate; -import com.google.common.base.Predicates; -import com.google.common.base.Supplier; -import com.google.common.collect.Iterables; -import com.google.common.collect.Sets; - -/** things which it seems should be in guava, but i can't find - * @author alex */ -public class CollectionFunctionals { - - private static final class EqualsSetPredicate implements Predicate<Iterable<?>> { - private final Iterable<?> target; - - private EqualsSetPredicate(Iterable<?> target) { - this.target = target; - } - - @Override - public boolean apply(@Nullable Iterable<?> input) { - if (input==null) return false; - return Sets.newHashSet(target).equals(Sets.newHashSet(input)); - } - } - - private static final class KeysOfMapFunction<K> implements Function<Map<K, ?>, Set<K>> { - @Override - public Set<K> apply(Map<K, ?> input) { - if (input==null) return null; - return input.keySet(); - } - - @Override public String toString() { return "keys"; } - } - - private static final class SizeSupplier implements Supplier<Integer> { - private final Iterable<?> collection; - - private SizeSupplier(Iterable<?> collection) { - this.collection = collection; - } - - @Override - public Integer get() { - return Iterables.size(collection); - } - - @Override public String toString() { return "sizeSupplier("+collection+")"; } - } - - public static final class SizeFunction implements Function<Iterable<?>, Integer> { - private final Integer valueIfInputNull; - - private SizeFunction(Integer valueIfInputNull) { - this.valueIfInputNull = valueIfInputNull; - } - - @Override - public Integer apply(Iterable<?> input) { - if (input==null) return valueIfInputNull; - return Iterables.size(input); - } - - @Override public String toString() { return "sizeFunction"; } - } - - public static Supplier<Integer> sizeSupplier(final Iterable<?> collection) { - return new SizeSupplier(collection); - } - - public static Function<Iterable<?>, Integer> sizeFunction() { return sizeFunction(null); } - - public static Function<Iterable<?>, Integer> sizeFunction(final Integer valueIfInputNull) { - return new SizeFunction(valueIfInputNull); - } - - public static final class FirstElementFunction<T> implements Function<Iterable<? extends T>, T> { - private FirstElementFunction() { - } - - @Override - public T apply(Iterable<? extends T> input) { - if (input==null) return null; - return Iterables.get(input, 0); - } - - @Override public String toString() { return "firstElementFunction"; } - } - - public static <T> Function<Iterable<? extends T>, T> firstElement() { - return new FirstElementFunction<T>(); - } - - public static <K> Function<Map<K,?>,Set<K>> keys() { - return new KeysOfMapFunction<K>(); - } - - public static <K> Function<Map<K, ?>, Integer> mapSize() { - return mapSize(null); - } - - public static <K> Function<Map<K, ?>, Integer> mapSize(Integer valueIfNull) { - return Functions.compose(CollectionFunctionals.sizeFunction(valueIfNull), CollectionFunctionals.<K>keys()); - } - - /** default guava Equals predicate will reflect order of target, and will fail when matching against a list; - * this treats them both as sets */ - public static Predicate<Iterable<?>> equalsSetOf(Object... target) { - return equalsSet(Arrays.asList(target)); - } - public static Predicate<Iterable<?>> equalsSet(final Iterable<?> target) { - return new EqualsSetPredicate(target); - } - - public static Predicate<Iterable<?>> sizeEquals(int targetSize) { - return Predicates.compose(Predicates.equalTo(targetSize), CollectionFunctionals.sizeFunction()); - } - - public static Predicate<Iterable<?>> empty() { - return sizeEquals(0); - } - - public static Predicate<Iterable<?>> notEmpty() { - return Predicates.not(empty()); - } - - public static <K> Predicate<Map<K,?>> mapSizeEquals(int targetSize) { - return Predicates.compose(Predicates.equalTo(targetSize), CollectionFunctionals.<K>mapSize()); - } - - public static <T,I extends Iterable<T>> Function<I, List<T>> limit(final int max) { - return new LimitFunction<T,I>(max); - } - - private static final class LimitFunction<T, I extends Iterable<T>> implements Function<I, List<T>> { - private final int max; - private LimitFunction(int max) { - this.max = max; - } - @Override - public List<T> apply(I input) { - if (input==null) return null; - MutableList<T> result = MutableList.of(); - for (T i: input) { - result.add(i); - if (result.size()>=max) - return result; - } - return result; - } - } - - // --------- - public static <I,T extends Collection<I>> Predicate<T> contains(I item) { - return new CollectionContains<I,T>(item); - } - - private static final class CollectionContains<I,T extends Collection<I>> implements Predicate<T> { - private final I item; - private CollectionContains(I item) { - this.item = item; - } - @Override - public boolean apply(T input) { - if (input==null) return false; - return input.contains(item); - } - @Override - public String toString() { - return "contains("+item+")"; - } - } - - // --------- - - public static <T,TT extends Iterable<T>> Predicate<TT> all(Predicate<T> attributeSatisfies) { - return quorum(QuorumChecks.all(), attributeSatisfies); - } - - public static <T,TT extends Iterable<T>> Predicate<TT> quorum(QuorumCheck quorumCheck, Predicate<T> attributeSatisfies) { - return new QuorumSatisfies<T, TT>(quorumCheck, attributeSatisfies); - } - - - private static final class QuorumSatisfies<I,T extends Iterable<I>> implements Predicate<T> { - private final Predicate<I> itemCheck; - private final QuorumCheck quorumCheck; - private QuorumSatisfies(QuorumCheck quorumCheck, Predicate<I> itemCheck) { - this.itemCheck = Preconditions.checkNotNull(itemCheck, "itemCheck"); - this.quorumCheck = Preconditions.checkNotNull(quorumCheck, "quorumCheck"); - } - @Override - public boolean apply(T input) { - if (input==null) return false; - int sizeHealthy = 0, totalSize = 0; - for (I item: input) { - totalSize++; - if (itemCheck.apply(item)) sizeHealthy++; - } - return quorumCheck.isQuorate(sizeHealthy, totalSize); - } - @Override - public String toString() { - return quorumCheck.toString()+"("+itemCheck+")"; - } - } - - - -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/brooklyn/util/collections/Jsonya.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/brooklyn/util/collections/Jsonya.java b/utils/common/src/main/java/brooklyn/util/collections/Jsonya.java deleted file mode 100644 index c917bd0..0000000 --- a/utils/common/src/main/java/brooklyn/util/collections/Jsonya.java +++ /dev/null @@ -1,581 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 brooklyn.util.collections; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.Stack; - -import javax.annotation.Nonnull; - -import brooklyn.util.guava.Maybe; -import brooklyn.util.text.StringEscapes.JavaStringEscapes; - -import com.google.common.annotations.Beta; -import com.google.common.base.Function; -import com.google.common.base.Functions; -import com.google.common.base.Preconditions; -import com.google.common.base.Throwables; -import com.google.common.primitives.Primitives; - -/** Jsonya = JSON-yet-another (tool) - * <p> - * provides conveniences for working with maps and lists containing maps and lists, - * and other datatypes too, easily convertible to json. - * <p> - * see {@link JsonyaTest} for examples - * - * @since 0.6.0 - **/ -@Beta -public class Jsonya { - - private Jsonya() {} - - /** creates a {@link Navigator} backed by the given map (focussed at the root) */ - public static <T extends Map<?,?>> Navigator<T> of(T map) { - return new Navigator<T>(map, MutableMap.class); - } - - /** creates a {@link Navigator} backed by the map at the focus of the given navigator */ - public static <T extends Map<?,?>> Navigator<T> of(Navigator<T> navigator) { - return new Navigator<T>(navigator.getFocusMap(), MutableMap.class); - } - - /** creates a {@link Navigator} backed by a newly created map; - * the map can be accessed by {@link Navigator#getMap()} */ - public static Navigator<MutableMap<Object,Object>> newInstance() { - return new Navigator<MutableMap<Object,Object>>(new MutableMap<Object,Object>(), MutableMap.class); - } - /** convenience for {@link Navigator#at(Object, Object...)} on a {@link #newInstance()} */ - public static Navigator<MutableMap<Object,Object>> at(Object ...pathSegments) { - return newInstance().atArray(pathSegments); - } - - /** as {@link #newInstance()} but using the given translator to massage objects inserted into the Jsonya structure */ - public static Navigator<MutableMap<Object,Object>> newInstanceTranslating(Function<Object,Object> translator) { - return newInstance().useTranslator(translator); - } - - /** as {@link #newInstanceTranslating(Function)} using an identity function - * (functionally equivalent to {@link #newInstance()} but explicit about it */ - public static Navigator<MutableMap<Object,Object>> newInstanceLiteral() { - return newInstanceTranslating(Functions.identity()); - } - - /** as {@link #newInstanceTranslating(Function)} using a function which only supports JSON primitives: - * maps and collections are traversed, strings and primitives are inserted, and everything else has toString applied. - * see {@link JsonPrimitiveDeepTranslator} */ - public static Navigator<MutableMap<Object,Object>> newInstancePrimitive() { - return newInstanceTranslating(new JsonPrimitiveDeepTranslator()); - } - - /** convenience for converting an object x to something which consists only of json primitives, doing - * {@link #toString()} on anything which is not recognised. see {@link JsonPrimitiveDeepTranslator} */ - public static Object convertToJsonPrimitive(Object x) { - if (x==null) return null; - if (x instanceof Map) return newInstancePrimitive().put((Map<?,?>)x).getRootMap(); - return newInstancePrimitive().put("data", x).getRootMap().get("data"); - } - - /** tells whether {@link #convertToJsonPrimitive(Object)} returns an object which is identical to - * the equivalent literal json structure. this is typically equivalent to saying serializing to json then - * deserializing will produce something where the result is equal to the input, - * modulo a few edge cases such as longs becoming ints. - * note that the converse (input equal to output) may not be the case, - * e.g. if the input contains special subclasses of collections of maps who care about type preservation. */ - public static boolean isJsonPrimitiveCompatible(Object x) { - if (x==null) return true; - return convertToJsonPrimitive(x).equals(x); - } - - @SuppressWarnings({"rawtypes","unchecked"}) - public static class Navigator<T extends Map<?,?>> { - - protected final Object root; - protected final Class<? extends Map> mapType; - protected Object focus; - protected Stack<Object> focusStack = new Stack<Object>(); - protected Function<Object,Void> creationInPreviousFocus; - protected Function<Object,Object> translator; - - public Navigator(Object backingStore, Class<? extends Map> mapType) { - this.root = Preconditions.checkNotNull(backingStore); - this.focus = backingStore; - this.mapType = mapType; - } - - // -------------- access and configuration - - /** returns the object at the focus, or null if none */ - public Object get() { - return focus; - } - - /** as {@link #get()} but always wrapped in a {@link Maybe}, absent if null */ - public @Nonnull Maybe<Object> getMaybe() { - return Maybe.fromNullable(focus); - } - - /** returns the object at the focus, casted to the given type, null if none - * @throws ClassCastException if object exists here but of the wrong type */ - public <V> V get(Class<V> type) { - return (V)focus; - } - - /** as {@link #get(Class)} but always wrapped in a {@link Maybe}, absent if null - * @throws ClassCastException if object exists here but of the wrong type */ - public @Nonnull <V> Maybe<V> getMaybe(Class<V> type) { - return Maybe.fromNullable(get(type)); - } - - /** gets the object at the indicated path from the current focus - * (without changing the path to that focus; use {@link #at(Object, Object...)} to change focus) */ - // Jun 2014, semantics changed so that focus does not change, which is more natural - public Object get(Object pathSegment, Object ...furtherPathSegments) { - push(); - at(pathSegment, furtherPathSegments); - Object result = get(); - pop(); - return result; - } - - public Navigator<T> root() { - focus = root; - return this; - } - - /** returns the object at the root */ - public Object getRoot() { - return root; - } - - /** returns the {@link Map} at the root, throwing if root is not a map */ - public T getRootMap() { - return (T) root; - } - - /** returns a {@link Map} at the given focus, creating if needed (so never null), - * throwing if it exists already and is not a map */ - public T getFocusMap() { - map(); - return (T)focus; - } - - /** as {@link #getFocusMap()} but always wrapped in a {@link Maybe}, absent if null - * @throws ClassCastException if object exists here but of the wrong type */ - public @Nonnull Maybe<T> getFocusMapMaybe() { - return Maybe.fromNullable(getFocusMap()); - } - - /** specifies a translator function to use when new data is added; - * by default everything is added as a literal (ie {@link Functions#identity()}), - * but if you want to do translation on the way in, - * set a translation function - * <p> - * note that translation should be idempotent as implementation may apply it multiple times in certain cases - */ - public Navigator<T> useTranslator(Function<Object,Object> translator) { - this.translator = translator; - return this; - } - - protected Object translate(Object x) { - if (translator==null) return x; - return translator.apply(x); - } - - protected Object translateKey(Object x) { - if (translator==null) return x; - // this could return the toString to make it strict json - // but json libraries seem to do that so not strictly necessary - return translator.apply(x); - } - - // ------------- navigation (map mainly) - - /** pushes the current focus to a stack, so that this location will be restored on the corresponding {@link #pop()} */ - public Navigator<T> push() { - focusStack.push(focus); - return this; - } - - /** pops the most recently pushed focus, so that it returns to the last location {@link #push()}ed */ - public Navigator<T> pop() { - focus = focusStack.pop(); - return this; - } - - /** returns the navigator moved to focus at the indicated key sequence in the given map */ - public Navigator<T> at(Object pathSegment, Object ...furtherPathSegments) { - down(pathSegment); - return atArray(furtherPathSegments); - } - public Navigator<T> atArray(Object[] furtherPathSegments) { - for (Object p: furtherPathSegments) - down(p); - return this; - } - - /** ensures the given focus is a map, creating if needed (and creating inside the list if it is in a list) */ - public Navigator<T> map() { - if (focus==null) { - focus = newMap(); - creationInPreviousFocus.apply(focus); - } - if (focus instanceof List) { - Map m = newMap(); - ((List)focus).add(translate(m)); - focus = m; - return this; - } - if (!(focus instanceof Map)) - throw new IllegalStateException("focus here is "+focus+"; expected a map"); - return this; - } - - /** puts the given key-value pair at the current focus (or multiple such), - * creating a map if needed, replacing any values stored against keys supplied here; - * if you wish to merge deep maps, see {@link #add(Object, Object...)} */ - public Navigator<T> put(Object k1, Object v1, Object ...kvOthers) { - map(); - putInternal((Map)focus, k1, v1, kvOthers); - return this; - } - - public Navigator<T> putIfNotNull(Object k1, Object v1) { - if (v1!=null) { - map(); - putInternal((Map)focus, k1, v1); - } - return this; - } - - protected void putInternal(Map target, Object k1, Object v1, Object ...kvOthers) { - assert (kvOthers.length % 2) == 0 : "even number of arguments required for put"; - target.put(translateKey(k1), translate(v1)); - for (int i=0; i<kvOthers.length; ) { - target.put(translateKey(kvOthers[i++]), translate(kvOthers[i++])); - } - } - - /** as {@link #put(Object, Object, Object...)} for the kv-pairs in the given map; ignores null for convenience */ - public Navigator<T> put(Map map) { - map(); - if (map==null) return this; - ((Map)focus).putAll((Map)translate(map)); - return this; - } - - protected Map newMap() { - try { - return mapType.newInstance(); - } catch (Exception e) { - throw Throwables.propagate(e); - } - } - - /** utility for {@link #at(Object, Object...)}, taking one argument at a time */ - protected Navigator<T> down(final Object pathSegment) { - if (focus instanceof List) { - return downList(pathSegment); - } - if ((focus instanceof Map) || focus==null) { - return downMap(pathSegment); - } - throw new IllegalStateException("focus here is "+focus+"; cannot descend to '"+pathSegment+"'"); - } - - protected Navigator<T> downMap(Object pathSegmentO) { - final Object pathSegment = translateKey(pathSegmentO); - final Map givenParentMap = (Map)focus; - if (givenParentMap!=null) { - creationInPreviousFocus = null; - focus = givenParentMap.get(pathSegment); - } - if (focus==null) { - final Function<Object, Void> previousCreation = creationInPreviousFocus; - creationInPreviousFocus = new Function<Object, Void>() { - public Void apply(Object input) { - creationInPreviousFocus = null; - Map parentMap = givenParentMap; - if (parentMap==null) { - parentMap = newMap(); - previousCreation.apply(parentMap); - } - parentMap.put(pathSegment, translate(input)); - return null; - } - }; - } - return this; - } - - protected Navigator<T> downList(final Object pathSegment) { - if (!(pathSegment instanceof Integer)) - throw new IllegalStateException("focus here is a list ("+focus+"); cannot descend to '"+pathSegment+"'"); - final List givenParentList = (List)focus; - // previous focus always non-null - creationInPreviousFocus = null; - focus = givenParentList.get((Integer)pathSegment); - if (focus==null) { - // don't need to worry about creation here; we don't create list entries simply by navigating - // TODO a nicer architecture would create a new object with focus for each traversal - // in that case we could create, filling other positions with null; but is there a need? - creationInPreviousFocus = new Function<Object, Void>() { - public Void apply(Object input) { - throw new IllegalStateException("cannot create "+input+" here because we are at a non-existent position in a list"); - } - }; - } - return this; - } - - // ------------- navigation (list mainly) - - /** ensures the given focus is a list */ - public Navigator<T> list() { - if (focus==null) { - focus = newList(); - creationInPreviousFocus.apply(focus); - } - if (!(focus instanceof List)) - throw new IllegalStateException("focus here is "+focus+"; expected a list"); - return this; - } - - protected List newList() { - return new ArrayList(); - } - - /** adds the given items to the focus, whether a list or a map, - * creating the focus as a map if it doesn't already exist. - * to add items to a list which might not exist, precede by a call to {@link #list()}. - * <p> - * when adding items to a list, iterable and array arguments are flattened because - * that makes the most sense when working with deep maps (adding one map to another where both contain lists, for example); - * to prevent flattening use {@link #addUnflattened(Object, Object...)} - * <p> - * when adding to a map, arguments will be treated as things to put into the map, - * accepting either multiple arguments, as key1, value1, key2, value2, ... - * (and must be an event number); or a single argument which must be a map, - * in which case the value for each key in the supplied map is added to any existing value against that key in the target map - * (in other words, it will do a "deep put", where nested maps are effectively merged) - * <p> - * this implementation will currently throw if you attempt to add a non-map to anything present which is not a list; - * auto-conversion to a list may be added in a future version - * */ - public Navigator<T> add(Object o1, Object ...others) { - if (focus==null) map(); - addInternal(focus, focus, o1, others); - return this; - } - - /** adds the given arguments to a list at this point (will not descend into maps, and will not flatten lists) */ - public Navigator<T> addUnflattened(Object o1, Object ...others) { - ((Collection)focus).add(translate(o1)); - for (Object oi: others) ((Collection)focus).add(translate(oi)); - return this; - } - - protected void addInternal(Object initialFocus, Object currentFocus, Object o1, Object ...others) { - if (currentFocus instanceof Map) { - Map target = (Map)currentFocus; - Map source; - if (others.length==0) { - // add as a map - if (o1==null) - // ignore if null - return ; - if (!(o1 instanceof Map)) - throw new IllegalStateException("cannot add: focus here is "+currentFocus+" (in "+initialFocus+"); expected a collection, or a map (with a map being added, not "+o1+")"); - source = (Map)translate(o1); - } else { - // build a source map from the arguments as key-value pairs - if ((others.length % 2)==0) - throw new IllegalArgumentException("cannot add an odd number of arguments to a map" + - " ("+o1+" then "+Arrays.toString(others)+" in "+currentFocus+" in "+initialFocus+")"); - source = MutableMap.of(translateKey(o1), translate(others[0])); - for (int i=1; i<others.length; ) - source.put(translateKey(others[i++]), translate(others[i++])); - } - // and add the source map to the target - for (Object entry : source.entrySet()) { - Object key = ((Map.Entry)entry).getKey(); - Object sv = ((Map.Entry)entry).getValue(); - Object tv = target.get(key); - if (!target.containsKey(key)) { - target.put(key, sv); - } else { - addInternal(initialFocus, tv, sv); - } - } - return; - } - // lists are easy to add to, but remember we have to flatten - if (!(currentFocus instanceof Collection)) - // TODO a nicer architecture might replace the current target with a list (also above where single non-map argument is supplied) - throw new IllegalStateException("cannot add: focus here is "+currentFocus+"; expected a collection"); - addFlattened((Collection)currentFocus, o1); - for (Object oi: others) addFlattened((Collection)currentFocus, oi); - } - - protected void addFlattened(Collection target, Object item) { - if (item instanceof Iterable) { - for (Object i: (Iterable)item) - addFlattened(target, i); - return; - } - if (item.getClass().isArray()) { - for (Object i: ((Object[])item)) - addFlattened(target, i); - return; - } - // nothing to flatten - target.add(translate(item)); - } - - /** Returns JSON serialized output for given focus in the given jsonya; - * applies a naive toString for specialized types */ - @Override - public String toString() { - return render(get()); - } - } - - public static String render(Object focus) { - if (focus instanceof Map) { - StringBuilder sb = new StringBuilder(); - sb.append("{"); - boolean first = true; - for (Object entry: ((Map<?,?>)focus).entrySet()) { - if (!first) sb.append(","); - else first = false; - sb.append(" "); - sb.append( render(((Map.Entry<?,?>)entry).getKey()) ); - sb.append(": "); - sb.append( render(((Map.Entry<?,?>)entry).getValue()) ); - } - sb.append(" }"); - return sb.toString(); - } - if (focus instanceof Collection) { - StringBuilder sb = new StringBuilder(); - sb.append("["); - boolean first = true; - for (Object entry: (Collection<?>)focus) { - if (!first) sb.append(","); - else first = false; - sb.append( render(entry) ); - } - sb.append(" ]"); - return sb.toString(); - } - if (focus instanceof String) { - return JavaStringEscapes.wrapJavaString((String)focus); - } - if (focus == null || focus instanceof Number || focus instanceof Boolean) - return ""+focus; - - return render(""+focus); - } - - /** Converts an object to one which uses standard JSON objects where possible - * (strings, numbers, booleans, maps, lists), and uses toString elsewhere */ - public static class JsonPrimitiveDeepTranslator implements Function<Object,Object> { - public static JsonPrimitiveDeepTranslator INSTANCE = new JsonPrimitiveDeepTranslator(); - - /** No need to instantiate except when subclassing. Use static {@link #INSTANCE}. */ - protected JsonPrimitiveDeepTranslator() {} - - @Override - public Object apply(Object input) { - return apply(input, new HashSet<Object>()); - } - - protected Object apply(Object input, Set<Object> stack) { - if (input==null) return applyNull(stack); - - if (isPrimitiveOrBoxer(input.getClass())) - return applyPrimitiveOrBoxer(input, stack); - - if (input instanceof String) - return applyString((String)input, stack); - - stack = new HashSet<Object>(stack); - if (!stack.add(input)) - // fail if object is self-recursive; don't even try toString as that is dangerous - // (extra measure of safety, since maps and lists generally fail elsewhere with recursive entries, - // eg in hashcode or toString) - return "[REF_ANCESTOR:"+stack.getClass()+"]"; - - if (input instanceof Collection<?>) - return applyCollection( (Collection<?>)input, stack ); - - if (input instanceof Map<?,?>) - return applyMap( (Map<?,?>)input, stack ); - - return applyOther(input, stack); - } - - protected Object applyNull(Set<Object> stack) { - return null; - } - - protected Object applyPrimitiveOrBoxer(Object input, Set<Object> stack) { - return input; - } - - protected Object applyString(String input, Set<Object> stack) { - return input.toString(); - } - - protected Object applyCollection(Collection<?> input, Set<Object> stack) { - MutableList<Object> result = MutableList.of(); - - for (Object xi: input) - result.add(apply(xi, stack)); - - return result; - } - - protected Object applyMap(Map<?, ?> input, Set<Object> stack) { - MutableMap<Object, Object> result = MutableMap.of(); - - for (Map.Entry<?,?> xi: input.entrySet()) - result.put(apply(xi.getKey(), stack), apply(xi.getValue(), stack)); - - return result; - } - - protected Object applyOther(Object input, Set<Object> stack) { - return input.toString(); - } - - public static boolean isPrimitiveOrBoxer(Class<?> type) { - return Primitives.allPrimitiveTypes().contains(type) || Primitives.allWrapperTypes().contains(type); - } - } - -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/brooklyn/util/collections/MutableList.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/brooklyn/util/collections/MutableList.java b/utils/common/src/main/java/brooklyn/util/collections/MutableList.java deleted file mode 100644 index c5cab8d..0000000 --- a/utils/common/src/main/java/brooklyn/util/collections/MutableList.java +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 brooklyn.util.collections; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -import javax.annotation.Nullable; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import brooklyn.util.exceptions.Exceptions; - -import com.google.common.collect.ImmutableList; - -public class MutableList<V> extends ArrayList<V> { - private static final long serialVersionUID = -5533940507175152491L; - - private static final Logger log = LoggerFactory.getLogger(MutableList.class); - - public static <V> MutableList<V> of() { - return new MutableList<V>(); - } - - public static <V> MutableList<V> of(V v1) { - MutableList<V> result = new MutableList<V>(); - result.add(v1); - return result; - } - - public static <V> MutableList<V> of(V v1, V v2, V ...vv) { - MutableList<V> result = new MutableList<V>(); - result.add(v1); - result.add(v2); - for (V v: vv) result.add(v); - return result; - } - - public static <V> MutableList<V> copyOf(@Nullable Iterable<? extends V> orig) { - return (orig instanceof Collection) - ? new MutableList<V>((Collection<? extends V>)orig) - : orig!=null ? new MutableList<V>(orig) : new MutableList<V>(); - } - - public static <E> MutableList<E> copyOf(Iterator<? extends E> elements) { - if (!elements.hasNext()) { - return of(); - } - return new MutableList.Builder<E>().addAll(elements).build(); - } - - public MutableList() { - } - - public MutableList(Collection<? extends V> source) { - super(source); - } - - public MutableList(Iterable<? extends V> source) { - for (V s : source) { - add(s); - } - } - - /** @deprecated since 0.7.0, use {@link #asImmutableCopy()}, or {@link #asUnmodifiable()} / {@link #asUnmodifiableCopy()} */ @Deprecated - public ImmutableList<V> toImmutable() { - return ImmutableList.copyOf(this); - } - /** creates an {@link ImmutableList} which is a copy of this list. note that the list should not contain nulls. */ - public List<V> asImmutableCopy() { - try { - return ImmutableList.copyOf(this); - } catch (Exception e) { - Exceptions.propagateIfFatal(e); - log.warn("Error converting list to Immutable, using unmodifiable instead: "+e, e); - return asUnmodifiableCopy(); - } - } - /** creates a {@link Collections#unmodifiableList(List)} wrapper around this list. the method is efficient, - * as there is no copying, but the returned view might change if the list here is changed. */ - public List<V> asUnmodifiable() { - return Collections.unmodifiableList(this); - } - /** creates a {@link Collections#unmodifiableList(List)} of a copy of this list. - * the returned item is immutable, but unlike {@link #asImmutableCopy()} nulls are permitted. */ - public List<V> asUnmodifiableCopy() { - return Collections.unmodifiableList(MutableList.copyOf(this)); - } - - public static <V> Builder<V> builder() { - return new Builder<V>(); - } - - /** - * @see guava's ImMutableList.Builder - */ - public static class Builder<V> { - final MutableList<V> result = new MutableList<V>(); - - public Builder() {} - - public Builder<V> add(V value) { - result.add(value); - return this; - } - - public Builder<V> add(V value1, V value2, V ...values) { - result.add(value1); - result.add(value2); - for (V v: values) result.add(v); - return this; - } - - public Builder<V> remove(V val) { - result.remove(val); - return this; - } - - public Builder<V> addAll(Iterable<? extends V> iterable) { - if (iterable instanceof Collection) { - result.addAll((Collection<? extends V>) iterable); - } else { - for (V v : iterable) { - result.add(v); - } - } - return this; - } - - public Builder<V> addAll(Iterator<? extends V> iter) { - while (iter.hasNext()) { - add(iter.next()); - } - return this; - } - - public Builder<V> addAll(V[] vals) { - for (V v : vals) { - result.add(v); - } - return this; - } - - public Builder<V> removeAll(Iterable<? extends V> iterable) { - if (iterable instanceof Collection) { - result.removeAll((Collection<? extends V>) iterable); - } else { - for (V v : iterable) { - result.remove(v); - } - } - return this; - } - - public MutableList<V> build() { - return new MutableList<V>(result); - } - - public ImmutableList<V> buildImmutable() { - return ImmutableList.copyOf(result); - } - - public Builder<V> addLists(Iterable<? extends V> ...items) { - for (Iterable<? extends V> item: items) { - addAll(item); - } - return this; - } - } - - /** as {@link List#add(Object)} but fluent style */ - public MutableList<V> append(V item) { - add(item); - return this; - } - - /** as {@link List#add(Object)} but excluding nulls, and fluent style */ - public MutableList<V> appendIfNotNull(V item) { - if (item!=null) add(item); - return this; - } - - /** as {@link List#add(Object)} but accepting multiple, and fluent style */ - public MutableList<V> append(V item1, V item2, V ...items) { - add(item1); - add(item2); - for (V item: items) add(item); - return this; - } - - /** as {@link List#add(Object)} but excluding nulls, accepting multiple, and fluent style */ - public MutableList<V> appendIfNotNull(V item1, V item2, V ...items) { - if (item1!=null) add(item1); - if (item2!=null) add(item2); - for (V item: items) - if (item!=null) add(item); - return this; - } - - /** as {@link List#addAll(Collection)} but fluent style */ - public MutableList<V> appendAll(Iterable<? extends V> items) { - if (items!=null) - for (V item: items) add(item); - return this; - } - /** as {@link List#addAll(Collection)} but fluent style */ - public MutableList<V> appendAll(Iterator<? extends V> items) { - addAll(items); - return this; - } - - public boolean addAll(Iterable<? extends V> setToAdd) { - // copy of parent, but accepting Iterable and null - if (setToAdd==null) return false; - return addAll(setToAdd.iterator()); - } - public boolean addAll(Iterator<? extends V> setToAdd) { - if (setToAdd==null) return false; - boolean modified = false; - while (setToAdd.hasNext()) { - if (add(setToAdd.next())) - modified = true; - } - return modified; - } - - public boolean removeIfNotNull(V item) { - if (item==null) return false; - return remove(item); - } - -}
