http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/Exceptions.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/Exceptions.java b/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/Exceptions.java new file mode 100644 index 0000000..347a212 --- /dev/null +++ b/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/Exceptions.java @@ -0,0 +1,284 @@ +/* + * 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 org.apache.brooklyn.util.exceptions; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Predicates.instanceOf; +import static com.google.common.base.Throwables.getCausalChain; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.UndeclaredThrowableException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.ExecutionException; + +import org.apache.brooklyn.util.text.Strings; + +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.base.Throwables; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; + +public class Exceptions { + + private static final List<Class<? extends Throwable>> BORING_THROWABLE_SUPERTYPES = ImmutableList.<Class<? extends Throwable>>of( + ExecutionException.class, InvocationTargetException.class, PropagatedRuntimeException.class, UndeclaredThrowableException.class); + + private static boolean isBoring(Throwable t) { + for (Class<? extends Throwable> type: BORING_THROWABLE_SUPERTYPES) + if (type.isInstance(t)) return true; + return false; + } + + private static final Predicate<Throwable> IS_THROWABLE_BORING = new Predicate<Throwable>() { + @Override + public boolean apply(Throwable input) { + return isBoring(input); + } + }; + + private static List<Class<? extends Throwable>> BORING_PREFIX_THROWABLE_EXACT_TYPES = ImmutableList.<Class<? extends Throwable>>of( + IllegalStateException.class, RuntimeException.class, CompoundRuntimeException.class); + + /** Returns whether this is throwable either known to be boring or to have an unuseful prefix; + * null is *not* boring. */ + public static boolean isPrefixBoring(Throwable t) { + if (t==null) return false; + if (isBoring(t)) + return true; + for (Class<? extends Throwable> type: BORING_PREFIX_THROWABLE_EXACT_TYPES) + if (t.getClass().equals(type)) return true; + return false; + } + + private static String stripBoringPrefixes(String s) { + ArrayList<String> prefixes = Lists.newArrayListWithCapacity(2 + BORING_PREFIX_THROWABLE_EXACT_TYPES.size() * 3); + for (Class<? extends Throwable> type : BORING_PREFIX_THROWABLE_EXACT_TYPES) { + prefixes.add(type.getCanonicalName()); + prefixes.add(type.getName()); + prefixes.add(type.getSimpleName()); + } + prefixes.add(":"); + prefixes.add(" "); + String[] ps = prefixes.toArray(new String[prefixes.size()]); + return Strings.removeAllFromStart(s, ps); + } + + /** + * Propagate a {@link Throwable} as a {@link RuntimeException}. + * <p> + * Like Guava {@link Throwables#propagate(Throwable)} but: + * <li> throws {@link RuntimeInterruptedException} to handle {@link InterruptedException}s; and + * <li> wraps as PropagatedRuntimeException for easier filtering + */ + public static RuntimeException propagate(Throwable throwable) { + if (throwable instanceof InterruptedException) + throw new RuntimeInterruptedException((InterruptedException) throwable); + Throwables.propagateIfPossible(checkNotNull(throwable)); + throw new PropagatedRuntimeException(throwable); + } + + /** + * Propagate exceptions which are fatal. + * <p> + * Propagates only those exceptions which one rarely (if ever) wants to capture, + * such as {@link InterruptedException} and {@link Error}s. + */ + public static void propagateIfFatal(Throwable throwable) { + if (throwable instanceof InterruptedException) + throw new RuntimeInterruptedException((InterruptedException) throwable); + if (throwable instanceof RuntimeInterruptedException) + throw (RuntimeInterruptedException) throwable; + if (throwable instanceof Error) + throw (Error) throwable; + } + + /** returns the first exception of the given type, or null */ + @SuppressWarnings("unchecked") + public static <T extends Throwable> T getFirstThrowableOfType(Throwable from, Class<T> clazz) { + return (T) Iterables.tryFind(getCausalChain(from), instanceOf(clazz)).orNull(); + } + + /** returns the first exception in the call chain which is not of common uninteresting types + * (ie excluding ExecutionException and PropagatedRuntimeExceptions); + * or the original throwable if all are uninteresting + */ + public static Throwable getFirstInteresting(Throwable throwable) { + return Iterables.tryFind(getCausalChain(throwable), Predicates.not(IS_THROWABLE_BORING)).or(throwable); + } + + /** creates (but does not throw) a new {@link PropagatedRuntimeException} whose + * message and cause are taken from the first _interesting_ element in the source */ + public static Throwable collapse(Throwable source) { + return collapse(source, true); + } + + /** as {@link #collapse(Throwable)} but includes causal messages in the message as per {@link #collapseTextIncludingAllCausalMessages(Throwable)}; + * use with care (limit once) as repeated usage can result in multiple copies of the same message */ + public static Throwable collapseIncludingAllCausalMessages(Throwable source) { + return collapse(source, true, true); + } + + /** creates (but does not throw) a new {@link PropagatedRuntimeException} whose + * message is taken from the first _interesting_ element in the source, + * and optionally also the causal chain */ + public static Throwable collapse(Throwable source, boolean collapseCausalChain) { + return collapse(source, collapseCausalChain, false); + } + + private static Throwable collapse(Throwable source, boolean collapseCausalChain, boolean includeAllCausalMessages) { + String message = ""; + Throwable collapsed = source; + int collapseCount = 0; + boolean messageIsFinal = false; + // remove boring stack traces at the head + while (isBoring(collapsed) && !messageIsFinal) { + collapseCount++; + Throwable cause = collapsed.getCause(); + if (cause==null) + // everything in the tree is boring... + return source; + String collapsedS = collapsed.getMessage(); + if (collapsed instanceof PropagatedRuntimeException && ((PropagatedRuntimeException)collapsed).isCauseEmbeddedInMessage()) { + message = collapsed.getMessage(); + messageIsFinal = true; + } else if (Strings.isNonBlank(collapsedS)) { + collapsedS = Strings.removeAllFromEnd(collapsedS, cause.toString(), stripBoringPrefixes(cause.toString()), cause.getMessage()); + collapsedS = stripBoringPrefixes(collapsedS); + if (Strings.isNonBlank(collapsedS)) + message = appendSeparator(message, collapsedS); + } + collapsed = cause; + } + // if no messages so far (ie we will be the toString) then remove boring prefixes from the message + Throwable messagesCause = collapsed; + while (messagesCause!=null && isPrefixBoring(messagesCause) && Strings.isBlank(message)) { + collapseCount++; + if (Strings.isNonBlank(messagesCause.getMessage())) { + message = messagesCause.getMessage(); + messagesCause = messagesCause.getCause(); + break; + } + messagesCause = messagesCause.getCause(); + } + + if (collapseCount==0 && !includeAllCausalMessages) + return source; + + if (collapseCount==0 && messagesCause!=null) { + message = messagesCause.toString(); + messagesCause = messagesCause.getCause(); + } + + if (Strings.isBlank(message)) { + return new PropagatedRuntimeException(collapseCausalChain ? collapsed : source); + } else { + if (messagesCause!=null && !messageIsFinal) { + String extraMessage = collapseText(messagesCause, includeAllCausalMessages); + message = appendSeparator(message, extraMessage); + } + return new PropagatedRuntimeException(message, collapseCausalChain ? collapsed : source, true); + } + } + + static String appendSeparator(String message, String next) { + if (Strings.isBlank(message)) + return next; + if (Strings.isBlank(next)) + return message; + if (message.endsWith(next)) + return message; + if (message.trim().endsWith(":") || message.trim().endsWith(";")) + return message.trim()+" "+next; + return message + ": " + next; + } + + /** removes uninteresting items from the top of the call stack (but keeps interesting messages), and throws + * @deprecated since 0.7.0 same as {@link #propagate(Throwable)} */ + public static RuntimeException propagateCollapsed(Throwable source) { + throw propagate(source); + } + + /** like {@link #collapse(Throwable)} but returning a one-line message suitable for logging without traces */ + public static String collapseText(Throwable t) { + return collapseText(t, false); + } + + /** normally {@link #collapseText(Throwable)} will stop following causal chains when encountering an interesting exception + * with a message; this variant will continue to follow such causal chains, showing all messages. + * for use e.g. when verbose is desired in the single-line message. */ + public static String collapseTextIncludingAllCausalMessages(Throwable t) { + return collapseText(t, true); + } + + private static String collapseText(Throwable t, boolean includeAllCausalMessages) { + if (t == null) return null; + Throwable t2 = collapse(t, true, includeAllCausalMessages); + if (t2 instanceof PropagatedRuntimeException) { + if (((PropagatedRuntimeException)t2).isCauseEmbeddedInMessage()) + // normally + return t2.getMessage(); + else if (t2.getCause()!=null) + return ""+t2.getCause(); + return ""+t2.getClass(); + } + String result = t2.toString(); + if (!includeAllCausalMessages) { + return result; + } + Throwable cause = t2.getCause(); + if (cause != null) { + String causeResult = collapseText(new PropagatedRuntimeException(cause)); + if (result.indexOf(causeResult)>=0) + return result; + return result + "; caused by "+causeResult; + } + return result; + } + + public static RuntimeException propagate(Collection<? extends Throwable> exceptions) { + throw propagate(create(exceptions)); + } + public static RuntimeException propagate(String prefix, Collection<? extends Throwable> exceptions) { + throw propagate(create(prefix, exceptions)); + } + + /** creates the given exception, but without propagating it, for use when caller will be wrapping */ + public static Throwable create(Collection<? extends Throwable> exceptions) { + return create(null, exceptions); + } + /** creates the given exception, but without propagating it, for use when caller will be wrapping */ + public static RuntimeException create(String prefix, Collection<? extends Throwable> exceptions) { + if (exceptions.size()==1) { + Throwable e = exceptions.iterator().next(); + if (Strings.isBlank(prefix)) return new PropagatedRuntimeException(e); + return new PropagatedRuntimeException(prefix + ": " + Exceptions.collapseText(e), e); + } + if (exceptions.isEmpty()) { + if (Strings.isBlank(prefix)) return new CompoundRuntimeException("(empty compound exception)", exceptions); + return new CompoundRuntimeException(prefix, exceptions); + } + if (Strings.isBlank(prefix)) return new CompoundRuntimeException(exceptions.size()+" errors, including: " + Exceptions.collapseText(exceptions.iterator().next()), exceptions); + return new CompoundRuntimeException(prefix+", "+exceptions.size()+" errors including: " + Exceptions.collapseText(exceptions.iterator().next()), exceptions); + } + +}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/FatalConfigurationRuntimeException.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/FatalConfigurationRuntimeException.java b/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/FatalConfigurationRuntimeException.java new file mode 100644 index 0000000..de425ed --- /dev/null +++ b/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/FatalConfigurationRuntimeException.java @@ -0,0 +1,33 @@ +/* + * 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 org.apache.brooklyn.util.exceptions; + +/** As {@link FatalRuntimeException} super, specialized for configuration errors. */ +public class FatalConfigurationRuntimeException extends FatalRuntimeException { + + private static final long serialVersionUID = -5361951925760434821L; + + public FatalConfigurationRuntimeException(String message) { + super(message); + } + + public FatalConfigurationRuntimeException(String message, Throwable cause) { + super(message, cause); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/FatalRuntimeException.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/FatalRuntimeException.java b/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/FatalRuntimeException.java new file mode 100644 index 0000000..6c16497 --- /dev/null +++ b/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/FatalRuntimeException.java @@ -0,0 +1,34 @@ +/* + * 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 org.apache.brooklyn.util.exceptions; + +/** Exception indicating a fatal error, typically used in CLI routines. + * The message supplied here should be suitable for display in a CLI response (without stack trace / exception class). */ +public class FatalRuntimeException extends UserFacingException { + + private static final long serialVersionUID = -3359163414517503809L; + + public FatalRuntimeException(String message) { + super(message); + } + + public FatalRuntimeException(String message, Throwable cause) { + super(message, cause); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/NotManagedException.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/NotManagedException.java b/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/NotManagedException.java new file mode 100644 index 0000000..3bf4fa0 --- /dev/null +++ b/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/NotManagedException.java @@ -0,0 +1,36 @@ +/* + * 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 org.apache.brooklyn.util.exceptions; + +public class NotManagedException extends IllegalStateException { + + private static final long serialVersionUID = -3359163414517503809L; + + public NotManagedException(Object object) { + super(object+" is not managed"); + } + + public NotManagedException(String message) { + super(message); + } + + public NotManagedException(String message, Throwable cause) { + super(message, cause); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/PropagatedRuntimeException.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/PropagatedRuntimeException.java b/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/PropagatedRuntimeException.java new file mode 100644 index 0000000..1b1aa5a --- /dev/null +++ b/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/PropagatedRuntimeException.java @@ -0,0 +1,70 @@ +/* + * 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 org.apache.brooklyn.util.exceptions; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** Indicates a runtime exception which has been propagated via {@link Exceptions#propagate} */ +public class PropagatedRuntimeException extends RuntimeException { + + private static final long serialVersionUID = 3959054308510077172L; + private static final Logger LOG = LoggerFactory.getLogger(PropagatedRuntimeException.class); + + private final boolean causeEmbeddedInMessage; + + /** Callers should typically *not* attempt to summarise the cause in the message here; use toString() to get extended information */ + public PropagatedRuntimeException(String message, Throwable cause) { + super(message, cause); + warnIfWrapping(cause); + causeEmbeddedInMessage = message.endsWith(Exceptions.collapseText(getCause())); + } + + public PropagatedRuntimeException(String message, Throwable cause, boolean causeEmbeddedInMessage) { + super(message, cause); + warnIfWrapping(cause); + this.causeEmbeddedInMessage = causeEmbeddedInMessage; + } + + public PropagatedRuntimeException(Throwable cause) { + super("" /* do not use default message as that destroys the toString */, cause); + warnIfWrapping(cause); + causeEmbeddedInMessage = false; + } + + private void warnIfWrapping(Throwable cause) { + if (LOG.isTraceEnabled() && cause instanceof PropagatedRuntimeException) { + LOG.trace("Wrapping a PropagatedRuntimeException in another PropagatedRuntimeException. Call chain:", new Exception()); + } + } + + @Override + public String toString() { + if (causeEmbeddedInMessage) { + return super.toString(); + } else { + return Exceptions.appendSeparator(super.toString(), Exceptions.collapseText(getCause())); + } + } + + public boolean isCauseEmbeddedInMessage() { + return causeEmbeddedInMessage; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/ReferenceWithError.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/ReferenceWithError.java b/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/ReferenceWithError.java new file mode 100644 index 0000000..87fa3f2 --- /dev/null +++ b/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/ReferenceWithError.java @@ -0,0 +1,101 @@ +/* + * 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 org.apache.brooklyn.util.exceptions; + +import javax.annotation.Nullable; + +import com.google.common.annotations.Beta; +import com.google.common.base.Supplier; + +/** A reference to an object which can carry an object alongside it. */ +@Beta +public class ReferenceWithError<T> implements Supplier<T> { + + private final T object; + private final Throwable error; + private final boolean maskError; + + /** returns a reference which includes an error, and where attempts to get the content cause the error to throw */ + public static <T> ReferenceWithError<T> newInstanceThrowingError(T object, Throwable error) { + return new ReferenceWithError<T>(object, error, false); + } + + /** returns a reference which includes an error, but attempts to get the content do not cause the error to throw */ + public static <T> ReferenceWithError<T> newInstanceMaskingError(T object, Throwable error) { + return new ReferenceWithError<T>(object, error, true); + } + + /** returns a reference which includes an error, but attempts to get the content do not cause the error to throw */ + public static <T> ReferenceWithError<T> newInstanceWithoutError(T object) { + return new ReferenceWithError<T>(object, null, false); + } + + protected ReferenceWithError(@Nullable T object, @Nullable Throwable error, boolean maskError) { + this.object = object; + this.error = error; + this.maskError = maskError; + } + + /** whether this will mask any error on an attempt to {@link #get()}; + * if false (if created with {@link #newInstanceThrowingError(Object, Throwable)}) a call to {@link #get()} will throw if there is an error; + * true if created with {@link #newInstanceMaskingError(Object, Throwable)} and {@link #get()} will not throw */ + public boolean masksErrorIfPresent() { + return maskError; + } + + /** returns the underlying value, throwing if there is an error which is not masked (ie {@link #throwsErrorOnAccess()} is set) */ + public T get() { + if (masksErrorIfPresent()) { + return getWithoutError(); + } + return getWithError(); + } + + /** returns the object, ignoring any error (even non-masked) */ + public T getWithoutError() { + return object; + } + + /** throws error, even if there is one (even if masked), else returns the object */ + public T getWithError() { + checkNoError(); + return object; + } + + /** throws if there is an error (even if masked) */ + public void checkNoError() { + if (hasError()) + Exceptions.propagate(error); + } + + /** returns the error (not throwing) */ + public Throwable getError() { + return error; + } + + /** true if there is an error (whether masked or not) */ + public boolean hasError() { + return error!=null; + } + + @Override + public String toString() { + return getClass().getSimpleName()+"["+object+(error!=null?"/"+(maskError?"masking:":"throwing:")+error:"")+"]"; + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/RuntimeInterruptedException.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/RuntimeInterruptedException.java b/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/RuntimeInterruptedException.java new file mode 100644 index 0000000..7ebb581 --- /dev/null +++ b/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/RuntimeInterruptedException.java @@ -0,0 +1,50 @@ +/* + * 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 org.apache.brooklyn.util.exceptions; + +/** + * A {@link RuntimeException} that is thrown when a Thread is interrupted. + * <p> + * This exception is useful if a Thread needs to be interrupted, but the {@link InterruptedException} can't be thrown + * because it is checked. + * <p> + * When the {@link RuntimeInterruptedException} is created, it will automatically set the interrupt status on the calling + * thread. + * + * @author Peter Veentjer. + */ +public class RuntimeInterruptedException extends RuntimeException { + + private static final long serialVersionUID = 915050245927866175L; + + public RuntimeInterruptedException(InterruptedException cause) { + super(cause); + Thread.currentThread().interrupt(); + } + + public RuntimeInterruptedException(String msg, InterruptedException cause) { + super(msg, cause); + Thread.currentThread().interrupt(); + } + + @Override + public InterruptedException getCause() { + return (InterruptedException) super.getCause(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/RuntimeTimeoutException.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/RuntimeTimeoutException.java b/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/RuntimeTimeoutException.java new file mode 100644 index 0000000..b13e0cf --- /dev/null +++ b/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/RuntimeTimeoutException.java @@ -0,0 +1,36 @@ +/* + * 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 org.apache.brooklyn.util.exceptions; + +public class RuntimeTimeoutException extends IllegalStateException { + + private static final long serialVersionUID = -3359163414517503809L; + + public RuntimeTimeoutException() { + super("timeout"); + } + + public RuntimeTimeoutException(String message) { + super(message); + } + + public RuntimeTimeoutException(String message, Throwable cause) { + super(message, cause); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/UserFacingException.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/UserFacingException.java b/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/UserFacingException.java new file mode 100644 index 0000000..34673e6 --- /dev/null +++ b/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/UserFacingException.java @@ -0,0 +1,39 @@ +/* + * 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 org.apache.brooklyn.util.exceptions; + +/** marker interface, to show that an exception is suitable for pretty-printing to an end-user, + * without including a stack trace */ +public class UserFacingException extends RuntimeException { + + private static final long serialVersionUID = 2216885527195571323L; + + public UserFacingException(String message) { + super(message); + } + + public UserFacingException(Throwable cause) { + super(cause.getMessage(), cause); + } + + public UserFacingException(String message, Throwable cause) { + super(message, cause); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/org/apache/brooklyn/util/git/GithubUrls.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/git/GithubUrls.java b/utils/common/src/main/java/org/apache/brooklyn/util/git/GithubUrls.java new file mode 100644 index 0000000..067bee9 --- /dev/null +++ b/utils/common/src/main/java/org/apache/brooklyn/util/git/GithubUrls.java @@ -0,0 +1,42 @@ +/* + * 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 org.apache.brooklyn.util.git; + +import org.apache.brooklyn.util.net.Urls; + +public class GithubUrls { + + public static String BASE_URL = "https://github.com/"; + + /** returns URL for the root of the given repo */ + public static String root(String owner, String repo) { + return Urls.mergePaths(BASE_URL, owner, repo); + } + + /** returns URL for downloading a .tar.gz version of a tag of a repository */ + public static String tgz(String owner, String repo, String tag) { + return Urls.mergePaths(root(owner, repo), "archive", tag+".tar.gz"); + } + + /** returns URL for downloading a .zip version of a tag of a repository */ + public static String zip(String owner, String repo, String tag) { + return Urls.mergePaths(root(owner, repo), "archive", tag+".zip"); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/org/apache/brooklyn/util/guava/Functionals.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/guava/Functionals.java b/utils/common/src/main/java/org/apache/brooklyn/util/guava/Functionals.java new file mode 100644 index 0000000..4a9a8c4 --- /dev/null +++ b/utils/common/src/main/java/org/apache/brooklyn/util/guava/Functionals.java @@ -0,0 +1,151 @@ +/* + * 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 org.apache.brooklyn.util.guava; + +import java.util.concurrent.Callable; + +import org.apache.brooklyn.util.guava.IfFunctions.IfFunctionBuilderApplyingFirst; + +import com.google.common.base.Function; +import com.google.common.base.Functions; +import com.google.common.base.Predicate; +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; + +public class Functionals { + + /** applies f1 to the input, then the result of that is passed to f2 (note opposite semantics to {@link Functions#compose(Function, Function)} */ + public static <A,B,C> Function<A,C> chain(final Function<A,? extends B> f1, final Function<B,C> f2) { + return Functions.compose(f2, f1); + } + + /** applies f1 to the input, then f2 to that result, then f3 to that result */ + public static <A,B,C,D> Function<A,D> chain(final Function<A,? extends B> f1, final Function<B,? extends C> f2, final Function<C,D> f3) { + return chain(f1, chain(f2, f3)); + } + + /** applies f1 to the input, then f2 to that result, then f3 to that result, then f4 to that result */ + public static <A,B,C,D,E> Function<A,E> chain(final Function<A,? extends B> f1, final Function<B,? extends C> f2, final Function<C,? extends D> f3, final Function<D,E> f4) { + return chain(f1, chain(f2, chain(f3, f4))); + } + + /** @see IfFunctions */ + public static <I> IfFunctionBuilderApplyingFirst<I> ifEquals(I test) { + return IfFunctions.ifEquals(test); + } + + /** @see IfFunctions */ + public static <I> IfFunctionBuilderApplyingFirst<I> ifNotEquals(I test) { + return IfFunctions.ifNotEquals(test); + } + + /** @see IfFunctions */ + public static <I> IfFunctionBuilderApplyingFirst<I> ifPredicate(Predicate<I> test) { + return IfFunctions.ifPredicate(test); + } + + /** like guava equivalent but parametrises the input generic type, and allows tostring to be customised */ + public static final class ConstantFunction<I, O> implements Function<I, O> { + private final O constant; + private Object toStringDescription; + + public ConstantFunction(O constant) { + this(constant, null); + } + public ConstantFunction(O constant, Object toStringDescription) { + this.constant = constant; + this.toStringDescription = toStringDescription; + } + + @Override + public O apply(I input) { + return constant; + } + + @Override + public String toString() { + return toStringDescription==null ? "constant("+constant+")" : toStringDescription.toString(); + } + } + + /** like guava {@link Functions#forSupplier(Supplier)} but parametrises the input generic type */ + public static <I,O> Function<I,O> function(final Supplier<O> supplier) { + class SupplierAsFunction implements Function<I,O> { + @Override public O apply(I input) { + return supplier.get(); + } + @Override public String toString() { + return "function("+supplier+")"; + } + } + return new SupplierAsFunction(); + } + + public static <I> Function<I,Void> function(final Runnable runnable) { + class RunnableAsFunction implements Function<I,Void> { + @Override public Void apply(I input) { + runnable.run(); + return null; + } + } + return new RunnableAsFunction(); + } + + public static Runnable runnable(final Supplier<?> supplier) { + class SupplierAsRunnable implements Runnable { + @Override + public void run() { + supplier.get(); + } + } + return new SupplierAsRunnable(); + } + + public static <T> Callable<T> callable(final Supplier<T> supplier) { + class SupplierAsCallable implements Callable<T> { + @Override + public T call() { + return supplier.get(); + } + @Override + public String toString() { + return "callable("+supplier+")"; + } + } + return new SupplierAsCallable(); + } + public static <T,U> Callable<U> callable(Function<T,U> f, T x) { + return callable(Suppliers.compose(f, Suppliers.ofInstance(x))); + } + + public static <T> Predicate<T> predicate(final Function<T,Boolean> f) { + class FunctionAsPredicate implements Predicate<T> { + @Override + public boolean apply(T input) { + return f.apply(input); + } + @Override + public String toString() { + return "predicate("+f+")"; + } + } + return new FunctionAsPredicate(); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/org/apache/brooklyn/util/guava/IfFunctions.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/guava/IfFunctions.java b/utils/common/src/main/java/org/apache/brooklyn/util/guava/IfFunctions.java new file mode 100644 index 0000000..440c7e5 --- /dev/null +++ b/utils/common/src/main/java/org/apache/brooklyn/util/guava/IfFunctions.java @@ -0,0 +1,158 @@ +/* + * 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 org.apache.brooklyn.util.guava; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.google.common.annotations.Beta; +import com.google.common.base.Function; +import com.google.common.base.Functions; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.base.Supplier; + +/** Utilities for building {@link Function} instances which return specific values + * (or {@link Supplier} or {@link Function} instances) when certain predicates are satisfied, + * tested in order and returning the first matching, + * with support for an "else" default value if none are satisfied (null by default). */ +public class IfFunctions { + + public static <I,O> IfFunctionBuilder<I,O> newInstance(Class<I> testType, Class<O> returnType) { + return new IfFunctionBuilder<I,O>(); + } + + public static <I> IfFunctionBuilderApplyingFirst<I> ifPredicate(Predicate<? super I> test) { + return new IfFunctionBuilderApplyingFirst<I>(test); + } + public static <I> IfFunctionBuilderApplyingFirst<I> ifEquals(I test) { + return ifPredicate(Predicates.equalTo(test)); + } + public static <I> IfFunctionBuilderApplyingFirst<I> ifNotEquals(I test) { + return ifPredicate(Predicates.not(Predicates.equalTo(test))); + } + + @Beta + public static class IfFunction<I,O> implements Function<I,O> { + protected final Map<Predicate<? super I>,Function<? super I,? extends O>> tests = new LinkedHashMap<Predicate<? super I>,Function<? super I,? extends O>>(); + protected Function<? super I,? extends O> defaultFunction = null; + + protected IfFunction(IfFunction<I,O> input) { + this.tests.putAll(input.tests); + this.defaultFunction = input.defaultFunction; + } + + protected IfFunction() { + } + + @Override + public O apply(I input) { + for (Map.Entry<Predicate<? super I>,Function<? super I,? extends O>> test: tests.entrySet()) { + if (test.getKey().apply(input)) + return test.getValue().apply(input); + } + return defaultFunction==null ? null : defaultFunction.apply(input); + } + + @Override + public String toString() { + return "if["+tests+"]"+(defaultFunction!=null ? "-else["+defaultFunction+"]" : ""); + } + } + + @Beta + public static class IfFunctionBuilder<I,O> extends IfFunction<I,O> { + protected IfFunctionBuilder() { super(); } + protected IfFunctionBuilder(IfFunction<I,O> input) { super(input); } + + public IfFunction<I,O> build() { + return new IfFunction<I,O>(this); + } + + public IfFunctionBuilderApplying<I,O> ifPredicate(Predicate<I> test) { + return new IfFunctionBuilderApplying<I,O>(this, (Predicate<I>)test); + } + public IfFunctionBuilderApplying<I,O> ifEquals(I test) { + return ifPredicate(Predicates.equalTo(test)); + } + public IfFunctionBuilderApplying<I,O> ifNotEquals(I test) { + return ifPredicate(Predicates.not(Predicates.equalTo(test))); + } + + public IfFunctionBuilder<I,O> defaultValue(O defaultValue) { + return defaultApply(new Functionals.ConstantFunction<I,O>(defaultValue, defaultValue)); + } + @SuppressWarnings("unchecked") + public IfFunctionBuilder<I,O> defaultGet(Supplier<? extends O> defaultSupplier) { + return defaultApply((Function<I,O>)Functions.forSupplier(defaultSupplier)); + } + public IfFunctionBuilder<I,O> defaultApply(Function<? super I,? extends O> defaultFunction) { + IfFunctionBuilder<I, O> result = new IfFunctionBuilder<I,O>(this); + result.defaultFunction = defaultFunction; + return result; + } + } + + @Beta + public static class IfFunctionBuilderApplying<I,O> { + private IfFunction<I, O> input; + private Predicate<? super I> test; + + private IfFunctionBuilderApplying(IfFunction<I,O> input, Predicate<? super I> test) { + this.input = input; + this.test = test; + } + + public IfFunctionBuilder<I,O> value(O value) { + return apply(new Functionals.ConstantFunction<I,O>(value, value)); + } + @SuppressWarnings("unchecked") + public IfFunctionBuilder<I,O> get(Supplier<? extends O> supplier) { + return apply((Function<I,O>)Functions.forSupplier(supplier)); + } + public IfFunctionBuilder<I,O> apply(Function<? super I,? extends O> function) { + IfFunctionBuilder<I, O> result = new IfFunctionBuilder<I,O>(input); + result.tests.put(test, function); + return result; + } + } + + @Beta + public static class IfFunctionBuilderApplyingFirst<I> { + private Predicate<? super I> test; + + private IfFunctionBuilderApplyingFirst(Predicate<? super I> test) { + this.test = test; + } + + public <O> IfFunctionBuilder<I,O> value(O value) { + return apply(new Functionals.ConstantFunction<I,O>(value, value)); + } + @SuppressWarnings("unchecked") + public <O> IfFunctionBuilder<I,O> get(Supplier<? extends O> supplier) { + return apply((Function<I,O>)Functions.forSupplier(supplier)); + } + public <O> IfFunctionBuilder<I,O> apply(Function<? super I,? extends O> function) { + IfFunctionBuilder<I, O> result = new IfFunctionBuilder<I,O>(); + result.tests.put(test, function); + return result; + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/org/apache/brooklyn/util/guava/IllegalStateExceptionSupplier.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/guava/IllegalStateExceptionSupplier.java b/utils/common/src/main/java/org/apache/brooklyn/util/guava/IllegalStateExceptionSupplier.java new file mode 100644 index 0000000..deaba53 --- /dev/null +++ b/utils/common/src/main/java/org/apache/brooklyn/util/guava/IllegalStateExceptionSupplier.java @@ -0,0 +1,43 @@ +/* + * 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 org.apache.brooklyn.util.guava; + +import com.google.common.base.Supplier; + +public class IllegalStateExceptionSupplier implements Supplier<RuntimeException> { + + public static final IllegalStateExceptionSupplier EMPTY_EXCEPTION = new IllegalStateExceptionSupplier(); + + protected final String message; + protected final Throwable cause; + + public IllegalStateExceptionSupplier() { this(null, null); } + public IllegalStateExceptionSupplier(String message) { this(message, null); } + public IllegalStateExceptionSupplier(Throwable cause) { this(cause!=null ? cause.getMessage() : null, cause); } + public IllegalStateExceptionSupplier(String message, Throwable cause) { + this.message = message; + this.cause = cause; + } + + @Override + public RuntimeException get() { + return new IllegalStateException(message, cause); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/org/apache/brooklyn/util/guava/KeyTransformingLoadingCache.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/guava/KeyTransformingLoadingCache.java b/utils/common/src/main/java/org/apache/brooklyn/util/guava/KeyTransformingLoadingCache.java new file mode 100644 index 0000000..fa20fd9 --- /dev/null +++ b/utils/common/src/main/java/org/apache/brooklyn/util/guava/KeyTransformingLoadingCache.java @@ -0,0 +1,152 @@ +/* + * 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 org.apache.brooklyn.util.guava; + +import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutionException; + +import com.google.common.base.Function; +import com.google.common.cache.AbstractLoadingCache; +import com.google.common.cache.CacheStats; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.ImmutableMap; + +/** + * A cache that transforms its keys before deferring to a delegate {@link LoadingCache}. + */ +// Concise names welcome. +public class KeyTransformingLoadingCache<A, B, V> extends AbstractLoadingCache<A, V> { + + private final LoadingCache<B, V> delegate; + private final Function<A, B> keyTransformer; + + public KeyTransformingLoadingCache(LoadingCache<B, V> delegate, Function<A, B> keyTransformer) { + this.delegate = delegate; + this.keyTransformer = keyTransformer; + } + + public static <A, B, V> KeyTransformingLoadingCache<A, B, V> from(LoadingCache<B, V> delegate, Function<A, B> keyTransformer) { + return new KeyTransformingLoadingCache<A, B, V>(delegate, keyTransformer); + } + + protected Function<A, B> keyTransformer() { + return keyTransformer; + } + + protected LoadingCache<B, V> delegate() { + return delegate; + } + + @Override + public V getIfPresent(Object key) { + try { + @SuppressWarnings("unchecked") + A cast = (A) key; + return delegate().getIfPresent(keyTransformer().apply(cast)); + } catch (ClassCastException e) { + return null; + } + } + + @Override + public V get(A key, Callable<? extends V> valueLoader) throws ExecutionException { + return delegate().get(keyTransformer().apply(key), valueLoader); + } + + /** + * Undefined because we can't prohibit a surjective {@link #keyTransformer()}. + * @throws UnsupportedOperationException + */ + @Override + public ImmutableMap<A, V> getAllPresent(Iterable<?> keys) { + throw new UnsupportedOperationException("getAllPresent in "+getClass().getName() + " undefined"); + } + + @Override + public void put(A key, V value) { + delegate().put(keyTransformer().apply(key), value); + } + + @Override + public void invalidate(Object key) { + try { + @SuppressWarnings("unchecked") + A cast = (A) key; + delegate().invalidate(keyTransformer().apply(cast)); + } catch (ClassCastException e) { + // Ignore + } + } + + @Override + public void invalidateAll() { + delegate().invalidateAll(); + } + + @Override + public long size() { + return delegate().size(); + } + + @Override + public CacheStats stats() { + return delegate().stats(); + } + + @Override + public V get(A key) throws ExecutionException { + return delegate().get(keyTransformer().apply(key)); + } + + @Override + public void refresh(A key) { + delegate().refresh(keyTransformer().apply(key)); + } + + /** + * Undefined because input values are not tracked. + * @throws UnsupportedOperationException + */ + @Override + public ConcurrentMap<A, V> asMap() { + throw new UnsupportedOperationException("asMap in " + getClass().getName() + " undefined"); + } + + @Override + public void cleanUp() { + delegate().cleanUp(); + } + + // Users can avoid middle type parameter. + public static class KeyTransformingSameTypeLoadingCache<A, V> extends KeyTransformingLoadingCache<A, A, V> { + public KeyTransformingSameTypeLoadingCache(LoadingCache<A, V> delegate, Function<A, A> keyTransformer) { + super(delegate, keyTransformer); + } + + // IDE note: This was named `from` to be consistent with KeyTransformingLoadingCache but Intellij 13 + // claims a name clash with the superclass `from`: + // java: name clash: <A,V>from(LoadingCache<A,V>, Function<A,A>) in KeyTransformingSameTypeLoadingCache + // and <A,B,V>from(LoadingCache<B,V>, Function<A,B>) in KeyTransformingLoadingCache have the same erasure, + // yet neither hides the other + public static <A, V> KeyTransformingSameTypeLoadingCache<A, V> with(LoadingCache<A, V> delegate, Function<A, A> keyTransformer) { + return new KeyTransformingSameTypeLoadingCache<A, V>(delegate, keyTransformer); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/org/apache/brooklyn/util/guava/Maybe.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/guava/Maybe.java b/utils/common/src/main/java/org/apache/brooklyn/util/guava/Maybe.java new file mode 100644 index 0000000..2264362 --- /dev/null +++ b/utils/common/src/main/java/org/apache/brooklyn/util/guava/Maybe.java @@ -0,0 +1,296 @@ +/* + * 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 org.apache.brooklyn.util.guava; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.io.Serializable; +import java.lang.ref.SoftReference; +import java.util.Collections; +import java.util.Iterator; +import java.util.Set; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import org.apache.brooklyn.util.javalang.JavaClassNames; + +import com.google.common.annotations.Beta; +import com.google.common.base.Function; +import com.google.common.base.Objects; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; +import com.google.common.collect.AbstractIterator; +import com.google.common.collect.ImmutableSet; + +/** Like Guava Optional but permitting null and permitting errors to be thrown. */ +public abstract class Maybe<T> implements Serializable, Supplier<T> { + + private static final long serialVersionUID = -6372099069863179019L; + + public static <T> Maybe<T> absent() { + return new Absent<T>(); + } + + /** Creates an absent whose get throws an {@link IllegalStateException} with the indicated message. + * Both stack traces (the cause and the callers) are provided, which can be quite handy. */ + public static <T> Maybe<T> absent(final String message) { + return absent(new IllegalStateExceptionSupplier(message)); + } + + /** Creates an absent whose get throws an {@link IllegalStateException} with the indicated cause. + * Both stack traces (the cause and the callers) are provided, which can be quite handy. */ + public static <T> Maybe<T> absent(final Throwable cause) { + return absent(new IllegalStateExceptionSupplier(cause)); + } + + /** Creates an absent whose get throws an {@link IllegalStateException} with the indicated message and underlying cause. + * Both stack traces (the cause and the callers) are provided, which can be quite handy. */ + public static <T> Maybe<T> absent(final String message, final Throwable cause) { + return absent(new IllegalStateExceptionSupplier(message, cause)); + } + + /** Creates an absent whose get throws an {@link RuntimeException} generated on demand from the given supplier */ + public static <T> Maybe<T> absent(final Supplier<? extends RuntimeException> exceptionSupplier) { + return new Absent<T>(Preconditions.checkNotNull(exceptionSupplier)); + } + + public static <T> Maybe<T> of(@Nullable T value) { + return new Present<T>(value); + } + + /** creates an instance wrapping a {@link SoftReference}, so it might go absent later on */ + public static <T> Maybe<T> soft(T value) { + return softThen(value, null); + } + /** creates an instance wrapping a {@link SoftReference}, using the second item given if lost */ + public static <T> Maybe<T> softThen(T value, Maybe<T> ifEmpty) { + if (value==null) return of((T)null); + return new SoftlyPresent<T>(value).usingAfterExpiry(ifEmpty); + } + + /** like {@link Optional#fromNullable(Object)}, returns absent if the argument is null */ + public static <T> Maybe<T> fromNullable(@Nullable T value) { + if (value==null) return absent(); + return new Present<T>(value); + } + + public static <T> Maybe<T> of(final Optional<T> value) { + if (value.isPresent()) return new AbstractPresent<T>() { + private static final long serialVersionUID = -5735268814211401356L; + @Override + public T get() { + return value.get(); + } + }; + return absent(); + } + + public static <T> Maybe<T> of(final Supplier<T> value) { + return new AbstractPresent<T>() { + private static final long serialVersionUID = -5735268814211401356L; + @Override + public T get() { + return value.get(); + } + }; + } + + /** returns a Maybe containing the next element in the iterator, or absent if none */ + public static <T> Maybe<T> next(Iterator<T> iterator) { + return iterator.hasNext() ? Maybe.of(iterator.next()) : Maybe.<T>absent(); + } + + public abstract boolean isPresent(); + public abstract T get(); + + public boolean isAbsent() { + return !isPresent(); + } + public boolean isAbsentOrNull() { + return !isPresentAndNonNull(); + } + public boolean isPresentAndNonNull() { + return isPresent() && get()!=null; + } + + public T or(T nextValue) { + if (isPresent()) return get(); + return nextValue; + } + + public Maybe<T> or(Maybe<T> nextValue) { + if (isPresent()) return this; + return nextValue; + } + + public T or(Supplier<T> nextValue) { + if (isPresent()) return get(); + return nextValue.get(); + } + + public T orNull() { + if (isPresent()) return get(); + return null; + } + + public Set<T> asSet() { + if (isPresent()) return ImmutableSet.of(get()); + return Collections.emptySet(); + } + + public <V> Maybe<V> transform(final Function<? super T, V> f) { + if (isPresent()) return new AbstractPresent<V>() { + private static final long serialVersionUID = 325089324325L; + public V get() { + return f.apply(Maybe.this.get()); + } + }; + return absent(); + } + + /** + * Returns the value of each present instance from the supplied {@code maybes}, in order, + * skipping over occurrences of {@link Maybe#absent()}. Iterators are unmodifiable and are + * evaluated lazily. + * + * @see Optional#presentInstances(Iterable) + */ + @Beta + public static <T> Iterable<T> presentInstances(final Iterable<? extends Maybe<? extends T>> maybes) { + checkNotNull(maybes); + return new Iterable<T>() { + @Override + public Iterator<T> iterator() { + return new AbstractIterator<T>() { + private final Iterator<? extends Maybe<? extends T>> iterator = checkNotNull(maybes.iterator()); + + @Override + protected T computeNext() { + while (iterator.hasNext()) { + Maybe<? extends T> maybe = iterator.next(); + if (maybe.isPresent()) { return maybe.get(); } + } + return endOfData(); + } + }; + } + }; + } + + public static class Absent<T> extends Maybe<T> { + private static final long serialVersionUID = -757170462010887057L; + private final Supplier<? extends RuntimeException> exception; + public Absent() { + this(IllegalStateExceptionSupplier.EMPTY_EXCEPTION); + } + public Absent(Supplier<? extends RuntimeException> exception) { + this.exception = exception; + } + @Override + public boolean isPresent() { + return false; + } + @Override + public T get() { + throw getException(); + } + public RuntimeException getException() { + return exception.get(); + } + } + + public static abstract class AbstractPresent<T> extends Maybe<T> { + private static final long serialVersionUID = -2266743425340870492L; + protected AbstractPresent() { + } + @Override + public boolean isPresent() { + return true; + } + } + + public static class Present<T> extends AbstractPresent<T> { + private static final long serialVersionUID = 436799990500336015L; + private final T value; + protected Present(T value) { + this.value = value; + } + @Override + public T get() { + return value; + } + } + + public static class SoftlyPresent<T> extends Maybe<T> { + private static final long serialVersionUID = 436799990500336015L; + private final SoftReference<T> value; + private Maybe<T> defaultValue; + protected SoftlyPresent(@Nonnull T value) { + this.value = new SoftReference<T>(value); + } + @Override + public T get() { + T result = value.get(); + if (result!=null) return result; + if (defaultValue==null) throw new IllegalStateException("Softly present item has been GC'd"); + return defaultValue.get(); + } + @Override + public T orNull() { + T result = value.get(); + if (result!=null) return result; + if (defaultValue==null) return null; + return defaultValue.orNull(); + } + @Override + public boolean isPresent() { + return value.get()!=null || (defaultValue!=null && defaultValue.isPresent()); + } + public Maybe<T> solidify() { + return Maybe.fromNullable(value.get()); + } + SoftlyPresent<T> usingAfterExpiry(Maybe<T> defaultValue) { + this.defaultValue = defaultValue; + return this; + } + } + + @Override + public String toString() { + return JavaClassNames.simpleClassName(this)+"["+(isPresent()?"value="+get():"")+"]"; + } + + @Override + public int hashCode() { + if (!isPresent()) return Objects.hashCode(31, isPresent()); + return Objects.hashCode(31, get()); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Maybe)) return false; + Maybe<?> other = (Maybe<?>)obj; + if (!isPresent()) + return !other.isPresent(); + return Objects.equal(get(), other.get()); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/org/apache/brooklyn/util/guava/MaybeFunctions.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/guava/MaybeFunctions.java b/utils/common/src/main/java/org/apache/brooklyn/util/guava/MaybeFunctions.java new file mode 100644 index 0000000..905135c --- /dev/null +++ b/utils/common/src/main/java/org/apache/brooklyn/util/guava/MaybeFunctions.java @@ -0,0 +1,52 @@ +/* + * 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 org.apache.brooklyn.util.guava; + +import com.google.common.base.Function; + +public class MaybeFunctions { + + public static <T> Function<T, Maybe<T>> wrap() { + return new Function<T, Maybe<T>>() { + @Override + public Maybe<T> apply(T input) { + return Maybe.fromNullable(input); + } + }; + } + + public static <T> Function<Maybe<T>, T> get() { + return new Function<Maybe<T>, T>() { + @Override + public T apply(Maybe<T> input) { + return input.get(); + } + }; + } + + public static <T> Function<Maybe<T>, T> or(final T value) { + return new Function<Maybe<T>, T>() { + @Override + public T apply(Maybe<T> input) { + return input.or(value); + } + }; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/org/apache/brooklyn/util/guava/SerializablePredicate.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/guava/SerializablePredicate.java b/utils/common/src/main/java/org/apache/brooklyn/util/guava/SerializablePredicate.java new file mode 100644 index 0000000..737809f --- /dev/null +++ b/utils/common/src/main/java/org/apache/brooklyn/util/guava/SerializablePredicate.java @@ -0,0 +1,26 @@ +/* + * 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 org.apache.brooklyn.util.guava; + +import java.io.Serializable; + +import com.google.common.base.Predicate; + +public interface SerializablePredicate<T> extends Predicate<T>, Serializable { +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/org/apache/brooklyn/util/guava/TypeTokens.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/guava/TypeTokens.java b/utils/common/src/main/java/org/apache/brooklyn/util/guava/TypeTokens.java new file mode 100644 index 0000000..b37ea33 --- /dev/null +++ b/utils/common/src/main/java/org/apache/brooklyn/util/guava/TypeTokens.java @@ -0,0 +1,72 @@ +/* + * 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 org.apache.brooklyn.util.guava; + +import javax.annotation.Nullable; + +import com.google.common.reflect.TypeToken; + +public class TypeTokens { + + /** returns raw type, if it's raw, else null; + * used e.g. to set only one of the raw type or the type token, + * for instance to make serialized output nicer */ + @Nullable + public static <T> Class<? super T> getRawTypeIfRaw(@Nullable TypeToken<T> type) { + if (type==null || !type.equals(TypeToken.of(type.getRawType()))) { + return null; + } else { + return type.getRawType(); + } + } + + /** returns null if it's raw, else the type token */ + @Nullable + public static <T> TypeToken<T> getTypeTokenIfNotRaw(@Nullable TypeToken<T> type) { + if (type==null || type.equals(TypeToken.of(type.getRawType()))) { + return null; + } else { + return type; + } + } + + /** given either a token or a raw type, returns the raw type */ + public static <T> Class<? super T> getRawType(TypeToken<T> token, Class<? super T> raw) { + if (raw!=null) return raw; + if (token!=null) return token.getRawType(); + throw new IllegalStateException("Both indicators of type are null"); + } + + + /** given either a token or a raw type, returns the token */ + @SuppressWarnings("unchecked") + public static <T> TypeToken<T> getTypeToken(TypeToken<T> token, Class<? super T> raw) { + if (token!=null) return token; + if (raw!=null) return TypeToken.of((Class<T>)raw); + throw new IllegalStateException("Both indicators of type are null"); + } + + /** gets the Class<T> object from a token; normal methods return Class<? super T> which may technically be correct + * with generics but this sloppily but handily gives you Class<T> which is usually what you have anyway */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + public static <T> Class<T> getRawRawType(TypeToken<T> token) { + return (Class)token.getRawType(); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/org/apache/brooklyn/util/internal/BasicDelegatingSystemProperty.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/internal/BasicDelegatingSystemProperty.java b/utils/common/src/main/java/org/apache/brooklyn/util/internal/BasicDelegatingSystemProperty.java new file mode 100644 index 0000000..faa97ae --- /dev/null +++ b/utils/common/src/main/java/org/apache/brooklyn/util/internal/BasicDelegatingSystemProperty.java @@ -0,0 +1,36 @@ +/* + * 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 org.apache.brooklyn.util.internal; + +public class BasicDelegatingSystemProperty { + protected final StringSystemProperty delegate; + + public BasicDelegatingSystemProperty(String name) { + delegate = new StringSystemProperty(name); + } + public String getPropertyName() { + return delegate.getPropertyName(); + } + public boolean isAvailable() { + return delegate.isAvailable(); + } + public String toString() { + return delegate.toString(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/org/apache/brooklyn/util/internal/BooleanSystemProperty.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/internal/BooleanSystemProperty.java b/utils/common/src/main/java/org/apache/brooklyn/util/internal/BooleanSystemProperty.java new file mode 100644 index 0000000..6738aa1 --- /dev/null +++ b/utils/common/src/main/java/org/apache/brooklyn/util/internal/BooleanSystemProperty.java @@ -0,0 +1,29 @@ +/* + * 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 org.apache.brooklyn.util.internal; + +public class BooleanSystemProperty extends BasicDelegatingSystemProperty { + public BooleanSystemProperty(String name) { + super(name); + } + public boolean isEnabled() { + // actually access system property! + return Boolean.getBoolean(getPropertyName()); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/org/apache/brooklyn/util/internal/BrooklynSystemProperties.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/internal/BrooklynSystemProperties.java b/utils/common/src/main/java/org/apache/brooklyn/util/internal/BrooklynSystemProperties.java new file mode 100644 index 0000000..06b5a3b --- /dev/null +++ b/utils/common/src/main/java/org/apache/brooklyn/util/internal/BrooklynSystemProperties.java @@ -0,0 +1,39 @@ +/* + * 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 org.apache.brooklyn.util.internal; + +/** + * Convenience for retrieving well-defined system properties, including checking if they have been set etc. + */ +public class BrooklynSystemProperties { + + // TODO should these become ConfigKeys ? + + public static BooleanSystemProperty DEBUG = new BooleanSystemProperty("brooklyn.debug"); + public static BooleanSystemProperty EXPERIMENTAL = new BooleanSystemProperty("brooklyn.experimental"); + + /** controls how long jsch delays between commands it issues */ + // -Dbrooklyn.jsch.exec.delay=100 + public static IntegerSystemProperty JSCH_EXEC_DELAY = new IntegerSystemProperty("brooklyn.jsch.exec.delay"); + + /** allows specifying a particular geo lookup service (to lookup IP addresses), as the class FQN to use */ + // -Dbrooklyn.location.geo.HostGeoLookup=brooklyn.location.geo.UtraceHostGeoLookup + public static StringSystemProperty HOST_GEO_LOOKUP_IMPL = new StringSystemProperty("brooklyn.location.geo.HostGeoLookup"); + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/org/apache/brooklyn/util/internal/DoubleSystemProperty.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/internal/DoubleSystemProperty.java b/utils/common/src/main/java/org/apache/brooklyn/util/internal/DoubleSystemProperty.java new file mode 100644 index 0000000..6ee2c67 --- /dev/null +++ b/utils/common/src/main/java/org/apache/brooklyn/util/internal/DoubleSystemProperty.java @@ -0,0 +1,28 @@ +/* + * 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 org.apache.brooklyn.util.internal; + +public class DoubleSystemProperty extends BasicDelegatingSystemProperty { + public DoubleSystemProperty(String name) { + super(name); + } + public double getValue() { + return Double.parseDouble(delegate.getValue()); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/org/apache/brooklyn/util/internal/IntegerSystemProperty.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/internal/IntegerSystemProperty.java b/utils/common/src/main/java/org/apache/brooklyn/util/internal/IntegerSystemProperty.java new file mode 100644 index 0000000..db627ac --- /dev/null +++ b/utils/common/src/main/java/org/apache/brooklyn/util/internal/IntegerSystemProperty.java @@ -0,0 +1,28 @@ +/* + * 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 org.apache.brooklyn.util.internal; + +public class IntegerSystemProperty extends BasicDelegatingSystemProperty { + public IntegerSystemProperty(String name) { + super(name); + } + public int getValue() { + return Integer.parseInt(delegate.getValue()); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/org/apache/brooklyn/util/internal/StringSystemProperty.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/internal/StringSystemProperty.java b/utils/common/src/main/java/org/apache/brooklyn/util/internal/StringSystemProperty.java new file mode 100644 index 0000000..0f24580 --- /dev/null +++ b/utils/common/src/main/java/org/apache/brooklyn/util/internal/StringSystemProperty.java @@ -0,0 +1,50 @@ +/* + * 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 org.apache.brooklyn.util.internal; + +public class StringSystemProperty { + + // TODO replace usages of this and related items with ConfigKeys + + public StringSystemProperty(String name) { + this.propertyName = name; + } + + private final String propertyName; + + public String getPropertyName() { + return propertyName; + } + + public boolean isAvailable() { + String property = System.getProperty(getPropertyName()); + return property!=null; + } + public boolean isNonEmpty() { + String property = System.getProperty(getPropertyName()); + return property!=null && !property.equals(""); + } + public String getValue() { + return System.getProperty(getPropertyName()); + } + @Override + public String toString() { + return getPropertyName()+(isAvailable()?"="+getValue():"(unset)"); + } +}
