You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2015/08/18 13:00:51 UTC
[36/64] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/699b3f65/core/src/main/java/brooklyn/util/file/ArchiveTasks.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/file/ArchiveTasks.java b/core/src/main/java/brooklyn/util/file/ArchiveTasks.java
deleted file mode 100644
index b183f62..0000000
--- a/core/src/main/java/brooklyn/util/file/ArchiveTasks.java
+++ /dev/null
@@ -1,58 +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.file;
-
-import java.util.Map;
-
-import org.apache.brooklyn.api.management.TaskAdaptable;
-import org.apache.brooklyn.api.management.TaskFactory;
-
-import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.ResourceUtils;
-import brooklyn.util.net.Urls;
-import brooklyn.util.task.Tasks;
-
-public class ArchiveTasks {
-
- /** as {@link #deploy(ResourceUtils, Map, String, SshMachineLocation, String, String, String)} with the most common parameters */
- public static TaskFactory<?> deploy(final ResourceUtils optionalResolver, final String archiveUrl, final SshMachineLocation machine, final String destDir) {
- return deploy(optionalResolver, null, archiveUrl, machine, destDir, false, null, null);
- }
-
- /** returns a task which installs and unpacks the given archive, as per {@link ArchiveUtils#deploy(ResourceUtils, Map, String, SshMachineLocation, String, String, String)};
- * if allowNonarchivesOrKeepArchiveAfterDeploy is false, this task will fail if the item is not an archive;
- * in cases where the download type is not clear in the URL but is known by the caller, supply a optionalDestFile including the appropriate file extension */
- public static TaskFactory<?> deploy(final ResourceUtils resolver, final Map<String, ?> props, final String archiveUrl, final SshMachineLocation machine, final String destDir, final boolean allowNonarchivesOrKeepArchiveAfterDeploy, final String optionalTmpDir, final String optionalDestFile) {
- return new TaskFactory<TaskAdaptable<?>>() {
- @Override
- public TaskAdaptable<?> newTask() {
- return Tasks.<Void>builder().name("deploying "+Urls.getBasename(archiveUrl)).description("installing "+archiveUrl+" and unpacking to "+destDir).body(new Runnable() {
- @Override
- public void run() {
- boolean unpacked = ArchiveUtils.deploy(resolver, props, archiveUrl, machine, destDir, allowNonarchivesOrKeepArchiveAfterDeploy, optionalTmpDir, optionalDestFile);
- if (!unpacked && !allowNonarchivesOrKeepArchiveAfterDeploy) {
- throw new IllegalStateException("Unable to unpack archive from "+archiveUrl+"; not able to infer archive type");
- }
- }
- }).build();
- }
- };
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/699b3f65/core/src/main/java/brooklyn/util/file/ArchiveUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/file/ArchiveUtils.java b/core/src/main/java/brooklyn/util/file/ArchiveUtils.java
deleted file mode 100644
index d072b70..0000000
--- a/core/src/main/java/brooklyn/util/file/ArchiveUtils.java
+++ /dev/null
@@ -1,351 +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.file;
-
-import static java.lang.String.format;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.EnumSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.ResourceUtils;
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.javalang.StackTraceSimplifier;
-import brooklyn.util.net.Urls;
-import brooklyn.util.os.Os;
-import brooklyn.util.ssh.BashCommands;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.task.ssh.SshTasks;
-import brooklyn.util.text.Strings;
-
-import com.google.common.base.Charsets;
-import com.google.common.base.Preconditions;
-import com.google.common.io.Files;
-
-public class ArchiveUtils {
-
- private static final Logger log = LoggerFactory.getLogger(ArchiveUtils.class);
-
- // TODO Make this a ConfigKey on the machine location
- /** Number of attempts when copying a file to a remote server. */
- public static final int NUM_RETRIES_FOR_COPYING = 5;
-
- /**
- * The types of archive that are supported by Brooklyn.
- */
- public static enum ArchiveType {
- TAR,
- TGZ,
- TBZ,
- ZIP,
- JAR,
- WAR,
- EAR,
- UNKNOWN;
-
- /**
- * Zip format archives used by Java.
- */
- public static Set<ArchiveType> ZIP_ARCHIVES = EnumSet.of(ArchiveType.ZIP, ArchiveType.JAR, ArchiveType.WAR, ArchiveType.EAR);
-
- public static ArchiveUtils.ArchiveType of(String filename) {
- if (filename == null) return null;
- String ext = Files.getFileExtension(filename);
- try {
- return valueOf(ext.toUpperCase());
- } catch (IllegalArgumentException iae) {
- if (filename.toLowerCase().endsWith(".tar.gz")) {
- return TGZ;
- } else if (filename.toLowerCase().endsWith(".tar.bz") ||
- filename.toLowerCase().endsWith(".tar.bz2") ||
- filename.toLowerCase().endsWith(".tar.xz")) {
- return TBZ;
- } else {
- return UNKNOWN;
- }
- }
- }
-
- @Override
- public String toString() {
- if (UNKNOWN.equals(this)) {
- return "";
- } else {
- return name().toLowerCase();
- }
- }
- }
-
- /**
- * Returns the list of commands used to install support for an archive with the given name.
- */
- public static List<String> installCommands(String fileName) {
- List<String> commands = new LinkedList<String>();
- switch (ArchiveType.of(fileName)) {
- case TAR:
- case TGZ:
- case TBZ:
- commands.add(BashCommands.INSTALL_TAR);
- break;
- case ZIP:
- commands.add(BashCommands.INSTALL_UNZIP);
- break;
- case JAR:
- case WAR:
- case EAR:
- case UNKNOWN:
- break;
- }
- return commands;
- }
-
- /**
- * Returns the list of commands used to extract the contents of the archive with the given name.
- * <p>
- * Optionally, Java archives of type
- *
- * @see #extractCommands(String, String)
- */
- public static List<String> extractCommands(String fileName, String sourceDir, String targetDir, boolean extractJar) {
- return extractCommands(fileName, sourceDir, targetDir, extractJar, true);
- }
-
- /** as {@link #extractCommands(String, String, String, boolean)}, but also with option to keep the original */
- public static List<String> extractCommands(String fileName, String sourceDir, String targetDir, boolean extractJar, boolean keepOriginal) {
- List<String> commands = new LinkedList<String>();
- commands.add("cd " + targetDir);
- String sourcePath = Os.mergePathsUnix(sourceDir, fileName);
- switch (ArchiveType.of(fileName)) {
- case TAR:
- commands.add("tar xvf " + sourcePath);
- break;
- case TGZ:
- commands.add("tar xvfz " + sourcePath);
- break;
- case TBZ:
- commands.add("tar xvfj " + sourcePath);
- break;
- case ZIP:
- commands.add("unzip " + sourcePath);
- break;
- case JAR:
- case WAR:
- case EAR:
- if (extractJar) {
- commands.add("jar -xvf " + sourcePath);
- break;
- }
- case UNKNOWN:
- if (!sourcePath.equals(Urls.mergePaths(targetDir, fileName))) {
- commands.add("cp " + sourcePath + " " + targetDir);
- } else {
- keepOriginal = true;
- // else we'd just end up deleting it!
- // this branch will often lead to errors in any case, see the allowNonarchivesOrKeepArchiveAfterDeploy parameter
- // in ArchiveTasks which calls through to here and then fails in the case corresponding to this code branch
- }
- break;
- }
- if (!keepOriginal && !commands.isEmpty())
- commands.add("rm "+sourcePath);
- return commands;
- }
-
- /**
- * Returns the list of commands used to extract the contents of the archive with the given name.
- * <p>
- * The archive will be extracted in its current directory unless it is a Java archive of type {@code .jar},
- * {@code .war} or {@code .ear}, which will be left as is.
- *
- * @see #extractCommands(String, String, String, boolean)
- */
- public static List<String> extractCommands(String fileName, String sourceDir) {
- return extractCommands(fileName, sourceDir, ".", false);
- }
-
- /**
- * Deploys an archive file to a remote machine and extracts the contents.
- */
- public static void deploy(String archiveUrl, SshMachineLocation machine, String destDir) {
- deploy(MutableMap.<String, Object>of(), archiveUrl, machine, destDir);
- }
-
- /**
- * Deploys an archive file to a remote machine and extracts the contents.
- * <p>
- * Copies the archive file from the given URL to the destination directory and extracts
- * the contents. If the URL is a local directory, the contents are packaged as a Zip archive first.
- *
- * @see #deploy(String, SshMachineLocation, String, String)
- * @see #deploy(Map, String, SshMachineLocation, String, String, String)
- */
- public static void deploy(Map<String, ?> props, String archiveUrl, SshMachineLocation machine, String destDir) {
- if (Urls.isDirectory(archiveUrl)) {
- File zipFile = ArchiveBuilder.zip().entry(".", Urls.toFile(archiveUrl)).create();
- archiveUrl = zipFile.getAbsolutePath();
- }
-
- // Determine filename
- String destFile = archiveUrl.contains("?") ? archiveUrl.substring(0, archiveUrl.indexOf('?')) : archiveUrl;
- destFile = destFile.substring(destFile.lastIndexOf('/') + 1);
-
- deploy(props, archiveUrl, machine, destDir, destFile);
- }
-
- /**
- * Deploys an archive file to a remote machine and extracts the contents.
- * <p>
- * Copies the archive file from the given URL to a file in the destination directory and extracts
- * the contents.
- *
- * @see #deploy(String, SshMachineLocation, String)
- * @see #deploy(Map, String, SshMachineLocation, String, String, String)
- */
- public static void deploy(String archiveUrl, SshMachineLocation machine, String destDir, String destFile) {
- deploy(MutableMap.<String, Object>of(), archiveUrl, machine, destDir, destDir, destFile);
- }
- public static void deploy(Map<String, ?> props, String archiveUrl, SshMachineLocation machine, String destDir, String destFile) {
- deploy(props, archiveUrl, machine, destDir, destDir, destFile);
- }
- public static void deploy(Map<String, ?> props, String archiveUrl, SshMachineLocation machine, String tmpDir, String destDir, String destFile) {
- deploy(null, props, archiveUrl, machine, destDir, true, tmpDir, destFile);
- }
-
- /**
- * Deploys an archive file to a remote machine and extracts the contents.
- * <p>
- * Copies the archive file from the given URL to a file in a temporary directory and extracts
- * the contents in the destination directory. For Java archives of type {@code .jar},
- * {@code .war} or {@code .ear} the file is simply copied.
- *
- * @return true if the archive is downloaded AND unpacked; false if it is downloaded but not unpacked;
- * throws if there was an error downloading or, for known archive types, unpacking.
- *
- * @see #deploy(String, SshMachineLocation, String)
- * @see #deploy(Map, String, SshMachineLocation, String, String, String)
- * @see #install(SshMachineLocation, String, String, int)
- */
- public static boolean deploy(ResourceUtils resolver, Map<String, ?> props, String archiveUrl, SshMachineLocation machine, String destDir, boolean keepArchiveAfterUnpacking, String optionalTmpDir, String optionalDestFile) {
- String destFile = optionalDestFile;
- if (destFile==null) destFile = Urls.getBasename(Preconditions.checkNotNull(archiveUrl, "archiveUrl"));
- if (Strings.isBlank(destFile))
- throw new IllegalStateException("Not given filename and cannot infer archive type from '"+archiveUrl+"'");
-
- String tmpDir = optionalTmpDir;
- if (tmpDir==null) tmpDir=Preconditions.checkNotNull(destDir, "destDir");
- if (props==null) props = MutableMap.of();
- String destPath = Os.mergePaths(tmpDir, destFile);
-
- // Use the location mutex to prevent package manager locking issues
- machine.acquireMutex("installing", "installing archive");
- try {
- int result = install(resolver, props, machine, archiveUrl, destPath, NUM_RETRIES_FOR_COPYING);
- if (result != 0) {
- throw new IllegalStateException(format("Unable to install archive %s to %s", archiveUrl, machine));
- }
-
- // extract, now using task if available
- MutableList<String> commands = MutableList.copyOf(installCommands(destFile))
- .appendAll(extractCommands(destFile, tmpDir, destDir, false, keepArchiveAfterUnpacking));
- if (DynamicTasks.getTaskQueuingContext()!=null) {
- result = DynamicTasks.queue(SshTasks.newSshExecTaskFactory(machine, commands.toArray(new String[0])).summary("extracting archive").requiringExitCodeZero()).get();
- } else {
- result = machine.execCommands(props, "extracting content", commands);
- }
- if (result != 0) {
- throw new IllegalStateException(format("Failed to expand archive %s on %s", archiveUrl, machine));
- }
- return ArchiveType.of(destFile)!=ArchiveType.UNKNOWN;
- } finally {
- machine.releaseMutex("installing");
- }
- }
-
- /**
- * Installs a URL onto a remote machine.
- *
- * @see #install(Map, SshMachineLocation, String, String, int)
- */
- public static int install(SshMachineLocation machine, String urlToInstall, String target) {
- return install(MutableMap.<String, Object>of(), machine, urlToInstall, target, NUM_RETRIES_FOR_COPYING);
- }
-
- /**
- * Installs a URL onto a remote machine.
- *
- * @see #install(SshMachineLocation, String, String)
- * @see SshMachineLocation#installTo(Map, String, String)
- */
- public static int install(Map<String, ?> props, SshMachineLocation machine, String urlToInstall, String target, int numAttempts) {
- return install(null, props, machine, urlToInstall, target, numAttempts);
- }
-
- public static int install(ResourceUtils resolver, Map<String, ?> props, SshMachineLocation machine, String urlToInstall, String target, int numAttempts) {
- if (resolver==null) resolver = ResourceUtils.create(machine);
- Exception lastError = null;
- int retriesRemaining = numAttempts;
- int attemptNum = 0;
- do {
- attemptNum++;
- try {
- Tasks.setBlockingDetails("Installing "+urlToInstall+" at "+machine);
- // TODO would be nice to have this in a task (and the things within it!)
- return machine.installTo(resolver, props, urlToInstall, target);
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- lastError = e;
- String stack = StackTraceSimplifier.toString(e);
- if (stack.contains("net.schmizz.sshj.sftp.RemoteFile.write")) {
- log.warn("Failed to transfer "+urlToInstall+" to "+machine+", retryable error, attempt "+attemptNum+"/"+numAttempts+": "+e);
- continue;
- }
- log.warn("Failed to transfer "+urlToInstall+" to "+machine+", not a retryable error so failing: "+e);
- throw Exceptions.propagate(e);
- } finally {
- Tasks.resetBlockingDetails();
- }
- } while (retriesRemaining --> 0);
- throw Exceptions.propagate(lastError);
- }
-
- /**
- * Copies the entire contents of a file to a String.
- *
- * @see com.google.common.io.Files#toString(File, java.nio.charset.Charset)
- */
- public static String readFullyString(File sourceFile) {
- try {
- return Files.toString(sourceFile, Charsets.UTF_8);
- } catch (IOException ioe) {
- throw Exceptions.propagate(ioe);
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/699b3f65/core/src/main/java/brooklyn/util/flags/ClassCoercionException.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/flags/ClassCoercionException.java b/core/src/main/java/brooklyn/util/flags/ClassCoercionException.java
deleted file mode 100644
index 17385ac..0000000
--- a/core/src/main/java/brooklyn/util/flags/ClassCoercionException.java
+++ /dev/null
@@ -1,39 +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.flags;
-
-/**
- * Thrown to indicate that {@link TypeCoercions} could not cast an object from one
- * class to another.
- */
-public class ClassCoercionException extends ClassCastException {
- public ClassCoercionException() {
- super();
- }
-
- /**
- * Constructs a <code>ClassCoercionException</code> with the specified
- * detail message.
- *
- * @param s the detail message.
- */
- public ClassCoercionException(String s) {
- super(s);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/699b3f65/core/src/main/java/brooklyn/util/flags/FlagUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/flags/FlagUtils.java b/core/src/main/java/brooklyn/util/flags/FlagUtils.java
deleted file mode 100644
index 0e596ac..0000000
--- a/core/src/main/java/brooklyn/util/flags/FlagUtils.java
+++ /dev/null
@@ -1,587 +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.flags;
-
-import static brooklyn.util.GroovyJavaMethods.elvis;
-import static brooklyn.util.GroovyJavaMethods.truth;
-import static com.google.common.base.Preconditions.checkNotNull;
-import groovy.lang.Closure;
-import groovy.lang.GroovyObject;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.Set;
-
-import org.apache.brooklyn.api.entity.trait.Configurable;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.config.ConfigKey;
-import brooklyn.config.ConfigKey.HasConfigKey;
-import brooklyn.util.GroovyJavaMethods;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.guava.Maybe;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.base.Throwables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-
-
-/** class to help transfer values passed as named arguments to other well-known variables/fields/objects;
- * see the test case for example usage */
-public class FlagUtils {
-
- public static final Logger log = LoggerFactory.getLogger(FlagUtils.class);
-
- private FlagUtils() {}
-
- /** see {@link #setFieldsFromFlags(Object o, ConfigBag)} */
- public static Map<?, ?> setPublicFieldsFromFlags(Map<?, ?> flags, Object o) {
- return setFieldsFromFlagsInternal(o, Arrays.asList(o.getClass().getFields()), flags, null, true);
- }
-
- /** see {@link #setFieldsFromFlags(Object, ConfigBag)} */
- public static Map<?, ?> setFieldsFromFlags(Map<?, ?> flags, Object o) {
- return setFieldsFromFlagsInternal(o, getAllFields(o.getClass()), flags, null, true);
- }
-
- /** sets all fields (including private and static, local and inherited) annotated {@link SetFromFlag} on the given object,
- * from the given flags map, returning just those flag-value pairs passed in which do not correspond to SetFromFlags fields
- * annotated ConfigKey and HasConfigKey fields are _configured_ (and we assume the object in that case is {@link Configurable});
- * keys should be ConfigKey, HasConfigKey, or String;
- * default values are also applied unless that is specified false on one of the variants of this method which takes such an argument
- */
- public static void setFieldsFromFlags(Object o, ConfigBag configBag) {
- setFieldsFromFlagsInternal(o, getAllFields(o.getClass()), configBag.getAllConfig(), configBag, true);
- }
-
- /** as {@link #setFieldsFromFlags(Object, ConfigBag)}, but allowing control over whether default values should be set */
- public static void setFieldsFromFlags(Object o, ConfigBag configBag, boolean setDefaultVals) {
- setFieldsFromFlagsInternal(o, getAllFields(o.getClass()), configBag.getAllConfig(), configBag, setDefaultVals);
- }
-
- /** as {@link #setFieldsFromFlags(Object, ConfigBag)}, but specifying a subset of flags to use */
- public static void setFieldsFromFlagsWithBag(Object o, Map<?,?> flags, ConfigBag configBag, boolean setDefaultVals) {
- setFieldsFromFlagsInternal(o, getAllFields(o.getClass()), flags, configBag, setDefaultVals);
- }
-
- /**
- * Sets the field with the given flag (if it exists) to the given value.
- * Will attempt to coerce the value to the required type.
- * Will respect "nullable" on the SetFromFlag annotation.
- *
- * @throws IllegalArgumentException If fieldVal is null and the SetFromFlag annotation set nullable=false
- */
- public static boolean setFieldFromFlag(Object o, String flagName, Object fieldVal) {
- return setFieldFromFlagInternal(checkNotNull(flagName, "flagName"), fieldVal, o, getAllFields(o.getClass()));
- }
-
- /** get all fields (including private and static) on the given object and all supertypes,
- * that are annotated with SetFromFlags.
- */
- public static Map<String, ?> getFieldsWithFlags(Object o) {
- return getFieldsWithFlagsInternal(o, getAllFields(o.getClass()));
- }
-
- /**
- * Finds the {@link Field} on the given object annotated with the given name flag.
- */
- public static Field findFieldForFlag(String flagName, Object o) {
- return findFieldForFlagInternal(flagName, o, getAllFields(o.getClass()));
- }
-
- /** get all fields (including private and static) and their values on the given object and all supertypes,
- * where the field is annotated with SetFromFlags.
- */
- public static Map<String, Object> getFieldsWithFlagsExcludingModifiers(Object o, int excludingModifiers) {
- List<Field> filteredFields = Lists.newArrayList();
- for (Field contender : getAllFields(o.getClass())) {
- if ((contender.getModifiers() & excludingModifiers) == 0) {
- filteredFields.add(contender);
- }
- }
- return getFieldsWithFlagsInternal(o, filteredFields);
- }
-
- /** get all fields with the given modifiers, and their values on the given object and all supertypes,
- * where the field is annotated with SetFromFlags.
- */
- public static Map<String, Object> getFieldsWithFlagsWithModifiers(Object o, int requiredModifiers) {
- List<Field> filteredFields = Lists.newArrayList();
- for (Field contender : getAllFields(o.getClass())) {
- if ((contender.getModifiers() & requiredModifiers) == requiredModifiers) {
- filteredFields.add(contender);
- }
- }
- return getFieldsWithFlagsInternal(o, filteredFields);
- }
-
- /** sets _all_ accessible _{@link ConfigKey}_ and {@link HasConfigKey} fields on the given object,
- * using the indicated flags/config-bag
- * @deprecated since 0.7.0 use {@link #setAllConfigKeys(Map, Configurable, boolean)} */
- public static Map<String, ?> setAllConfigKeys(Map<String, ?> flagsOrConfig, Configurable instance) {
- return setAllConfigKeys(flagsOrConfig, instance, false);
- }
- /** sets _all_ accessible _{@link ConfigKey}_ and {@link HasConfigKey} fields on the given object,
- * using the indicated flags/config-bag */
- public static Map<String, ?> setAllConfigKeys(Map<String, ?> flagsOrConfig, Configurable instance, boolean includeFlags) {
- ConfigBag bag = new ConfigBag().putAll(flagsOrConfig);
- setAllConfigKeys(instance, bag, includeFlags);
- return bag.getUnusedConfigMutable();
- }
-
- /** sets _all_ accessible _{@link ConfigKey}_ and {@link HasConfigKey} fields on the given object,
- * using the indicated flags/config-bag
- * @deprecated since 0.7.0 use {@link #setAllConfigKeys(Configurable, ConfigBag, boolean)} */
- public static void setAllConfigKeys(Configurable o, ConfigBag bag) {
- setAllConfigKeys(o, bag, false);
- }
- /** sets _all_ accessible _{@link ConfigKey}_ and {@link HasConfigKey} fields on the given object,
- * using the indicated flags/config-bag */
- public static void setAllConfigKeys(Configurable o, ConfigBag bag, boolean includeFlags) {
- for (Field f: getAllFields(o.getClass())) {
- ConfigKey<?> key = getFieldAsConfigKey(o, f);
- if (key!=null) {
- FlagConfigKeyAndValueRecord record = getFlagConfigKeyRecord(f, key, bag);
- if ((includeFlags && record.isValuePresent()) || record.getConfigKeyMaybeValue().isPresent()) {
- setField(o, f, record.getValueOrNullPreferringConfigKey(), null);
- }
- }
- }
- }
-
- public static class FlagConfigKeyAndValueRecord {
- private String flagName = null;
- private ConfigKey<?> configKey = null;
- private Maybe<Object> flagValue = Maybe.absent();
- private Maybe<Object> configKeyValue = Maybe.absent();
-
- public String getFlagName() {
- return flagName;
- }
- public ConfigKey<?> getConfigKey() {
- return configKey;
- }
- public Maybe<Object> getFlagMaybeValue() {
- return flagValue;
- }
- public Maybe<Object> getConfigKeyMaybeValue() {
- return configKeyValue;
- }
- public Object getValueOrNullPreferringConfigKey() {
- return getConfigKeyMaybeValue().or(getFlagMaybeValue()).orNull();
- }
- public Object getValueOrNullPreferringFlag() {
- return getFlagMaybeValue().or(getConfigKeyMaybeValue()).orNull();
- }
- /** true if value is present for either flag or config key */
- public boolean isValuePresent() {
- return flagValue.isPresent() || configKeyValue.isPresent();
- }
-
- @Override
- public String toString() {
- return Objects.toStringHelper(this).omitNullValues()
- .add("flag", flagName)
- .add("configKey", configKey)
- .add("flagValue", flagValue.orNull())
- .add("configKeyValue", configKeyValue.orNull())
- .toString();
- }
- }
-
- /** gets all the flags/keys in the given config bag which are applicable to the given type's config keys and flags */
- public static <T> List<FlagConfigKeyAndValueRecord> findAllFlagsAndConfigKeys(T optionalInstance, Class<? extends T> type, ConfigBag input) {
- List<FlagConfigKeyAndValueRecord> output = new ArrayList<FlagUtils.FlagConfigKeyAndValueRecord>();
- for (Field f: getAllFields(type)) {
- ConfigKey<?> key = getFieldAsConfigKey(optionalInstance, f);
- FlagConfigKeyAndValueRecord record = getFlagConfigKeyRecord(f, key, input);
- if (record.isValuePresent())
- output.add(record);
- }
- return output;
- }
-
- /** returns the flag/config-key record for the given input */
- private static FlagConfigKeyAndValueRecord getFlagConfigKeyRecord(Field f, ConfigKey<?> key, ConfigBag input) {
- FlagConfigKeyAndValueRecord result = new FlagConfigKeyAndValueRecord();
- result.configKey = key;
- if (key!=null && input.containsKey(key))
- result.configKeyValue = Maybe.<Object>of(input.getStringKey(key.getName()));
- SetFromFlag flag = f.getAnnotation(SetFromFlag.class);
- if (flag!=null) {
- result.flagName = flag.value();
- if (input.containsKey(flag.value()))
- result.flagValue = Maybe.of(input.getStringKey(flag.value()));
- }
- return result;
- }
-
- /** returns all fields on the given class, superclasses, and interfaces thereof, in that order of preference,
- * (excluding fields on Object) */
- public static List<Field> getAllFields(Class<?> base, Closure<Boolean> filter) {
- return getAllFields(base, GroovyJavaMethods.<Field>predicateFromClosure(filter));
- }
- public static List<Field> getAllFields(Class<?> base) {
- return getAllFields(base, Predicates.<Field>alwaysTrue());
- }
- public static List<Field> getAllFields(Class<?> base, Predicate<Field> filter) {
- return getLocalFields(getAllAssignableTypes(base), filter);
- }
- /** returns all fields explicitly declared on the given classes */
- public static List<Field> getLocalFields(List<Class<?>> classes) {
- return getLocalFields(classes, Predicates.<Field>alwaysTrue());
- }
- public static List<Field> getLocalFields(List<Class<?>> classes, Closure<Boolean> filter) {
- return getLocalFields(classes, GroovyJavaMethods.<Field>predicateFromClosure(filter));
- }
- public static List<Field> getLocalFields(List<Class<?>> classes, Predicate<Field> filter) {
- List<Field> fields = Lists.newArrayList();
- for (Class<?> c : classes) {
- for (Field f : c.getDeclaredFields()) {
- if (filter.apply(f)) fields.add(f);
- }
- }
- return fields;
- }
-
- /** returns base, superclasses, then interfaces */
- public static List<Class<?>> getAllAssignableTypes(Class<?> base) {
- return getAllAssignableTypes(base, new Predicate<Class<?>>() {
- @Override public boolean apply(Class<?> it) {
- return (it != Object.class) && (it != GroovyObject.class);
- }
- });
- }
- public static List<Class<?>> getAllAssignableTypes(Class<?> base, Closure<Boolean> filter) {
- return getAllAssignableTypes(base, GroovyJavaMethods.<Class<?>>predicateFromClosure(filter));
- }
- public static List<Class<?>> getAllAssignableTypes(Class<?> base, Predicate<Class<?>> filter) {
- List<Class<?>> classes = Lists.newArrayList();
- for (Class<?> c = base; c != null; c = c.getSuperclass()) {
- if (filter.apply(c)) classes.add(c);
- }
- for (int i=0; i<classes.size(); i++) {
- for (Class<?> interf : classes.get(i).getInterfaces()) {
- if (filter.apply(interf) && !(classes.contains(interf))) classes.add(interf);
- }
- }
- return classes;
- }
-
- private static Map<String, Object> getFieldsWithFlagsInternal(Object o, Collection<Field> fields) {
- Map<String, Object> result = Maps.newLinkedHashMap();
- for (Field f: fields) {
- SetFromFlag cf = f.getAnnotation(SetFromFlag.class);
- if (cf != null) {
- String flagName = elvis(cf.value(), f.getName());
- if (truth(flagName)) {
- result.put(flagName, getField(o, f));
- } else {
- log.warn("Ignoring field {} of object {} as no flag name available", f, o);
- }
- }
- }
- return result;
- }
-
- private static Field findFieldForFlagInternal(String flagName, Object o, Collection<Field> fields) {
- for (Field f: fields) {
- SetFromFlag cf = f.getAnnotation(SetFromFlag.class);
- if (cf != null) {
- String contenderName = elvis(cf.value(), f.getName());
- if (flagName.equals(contenderName)) {
- return f;
- }
- }
- }
- throw new NoSuchElementException("Field with flag "+flagName+" not found on "+o+" of type "+(o != null ? o.getClass() : null));
- }
-
- private static boolean setFieldFromFlagInternal(String flagName, Object fieldVal, Object o, Collection<Field> fields) {
- for (Field f: fields) {
- SetFromFlag cf = f.getAnnotation(SetFromFlag.class);
- if (cf != null && flagName.equals(elvis(cf.value(), f.getName()))) {
- setField(o, f, fieldVal, cf);
- return true;
- }
- }
- return false;
- }
-
- private static Map<String, ?> setFieldsFromFlagsInternal(Object o, Collection<Field> fields, Map<?,?> flagsOrConfig, ConfigBag bag, boolean setDefaultVals) {
- if (bag==null) bag = new ConfigBag().putAll(flagsOrConfig);
- for (Field f: fields) {
- SetFromFlag cf = f.getAnnotation(SetFromFlag.class);
- if (cf!=null) setFieldFromConfig(o, f, bag, cf, setDefaultVals);
- }
- return bag.getUnusedConfigMutable();
- }
-
- private static void setFieldFromConfig(Object o, Field f, ConfigBag bag, SetFromFlag optionalAnnotation, boolean setDefaultVals) {
- String flagName = optionalAnnotation==null ? null : (String)elvis(optionalAnnotation.value(), f.getName());
- // prefer flag name, if present
- if (truth(flagName) && bag.containsKey(flagName)) {
- setField(o, f, bag.getStringKey(flagName), optionalAnnotation);
- return;
- }
- // first check whether it is a key
- ConfigKey<?> key = getFieldAsConfigKey(o, f);
- if (key!=null && bag.containsKey(key)) {
- Object uncoercedValue = bag.getStringKey(key.getName());
- setField(o, f, uncoercedValue, optionalAnnotation);
- return;
- }
- if (setDefaultVals && optionalAnnotation!=null && truth(optionalAnnotation.defaultVal())) {
- Object oldValue;
- try {
- f.setAccessible(true);
- oldValue = f.get(o);
- if (oldValue==null || oldValue.equals(getDefaultValueForType(f.getType()))) {
- setField(o, f, optionalAnnotation.defaultVal(), optionalAnnotation);
- }
- } catch (Exception e) {
- Exceptions.propagate(e);
- }
- return;
- }
- }
-
- /** returns the given field as a config key, if it is an accessible config key, otherwise null */
- private static ConfigKey<?> getFieldAsConfigKey(Object optionalInstance, Field f) {
- if (optionalInstance==null) {
- if ((f.getModifiers() & Modifier.STATIC)==0)
- // non-static field on null instance, can't be set
- return null;
- }
- if (ConfigKey.class.isAssignableFrom(f.getType())) {
- return (ConfigKey<?>) getField(optionalInstance, f);
- } else if (HasConfigKey.class.isAssignableFrom(f.getType())) {
- return ((HasConfigKey<?>)getField(optionalInstance, f)).getConfigKey();
- }
- return null;
- }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public static void setConfig(Object objectOfField, ConfigKey<?> key, Object value, SetFromFlag optionalAnnotation) {
- if (objectOfField instanceof Configurable) {
- ((Configurable)objectOfField).setConfig((ConfigKey)key, value);
- return;
- } else {
- if (optionalAnnotation==null) {
- log.warn("Cannot set key "+key.getName()+" on "+objectOfField+": containing class is not Configurable");
- } else if (!key.getName().equals(optionalAnnotation.value())) {
- log.warn("Cannot set key "+key.getName()+" on "+objectOfField+" from flag "+optionalAnnotation.value()+": containing class is not Configurable");
- } else {
- // if key and flag are the same, then it will probably happen automatically
- if (log.isDebugEnabled())
- log.debug("Cannot set key "+key.getName()+" on "+objectOfField+" from flag "+optionalAnnotation.value()+": containing class is not Configurable");
- }
- return;
- }
- }
-
- /** sets the field to the value, after checking whether the given value can be set
- * respecting the constraints of the annotation
- */
- public static void setField(Object objectOfField, Field f, Object value, SetFromFlag optionalAnnotation) {
- try {
- ConfigKey<?> key = getFieldAsConfigKey(objectOfField, f);
- if (key!=null) {
- setConfig(objectOfField, key, value, optionalAnnotation);
- return;
- }
-
- if (!f.isAccessible()) f.setAccessible(true);
- if (optionalAnnotation!=null && optionalAnnotation.immutable()) {
- Object oldValue = f.get(objectOfField);
- if (!Objects.equal(oldValue, getDefaultValueForType(f.getType())) && oldValue != value) {
- throw new IllegalStateException("Forbidden modification to immutable field "+
- f+" in "+objectOfField+": attempting to change to "+value+" when was already "+oldValue);
- }
- }
- if (optionalAnnotation!=null && !optionalAnnotation.nullable() && value==null) {
- throw new IllegalArgumentException("Forbidden null assignment to non-nullable field "+
- f+" in "+objectOfField);
- }
- if (optionalAnnotation!=null && (f.getModifiers() & Modifier.STATIC)==Modifier.STATIC)
- log.warn("Setting static field "+f+" in "+objectOfField+" from flag "+optionalAnnotation.value()+": discouraged");
-
- Object newValue;
- try {
- newValue = TypeCoercions.coerce(value, f.getType());
- } catch (Exception e) {
- throw new IllegalArgumentException("Cannot set "+f+" in "+objectOfField+" from type "+value.getClass()+" ("+value+"): "+e, e);
- }
- f.set(objectOfField, newValue);
- if (log.isTraceEnabled()) log.trace("FlagUtils for "+objectOfField+", setting field="+f.getName()+"; val="+value+"; newVal="+newValue+"; key="+key);
-
- } catch (IllegalAccessException e) {
- throw Throwables.propagate(e);
- }
- }
-
- /** gets the value of the field.
- */
- public static Object getField(Object objectOfField, Field f) {
- try {
- if (!f.isAccessible()) f.setAccessible(true);
- return f.get(objectOfField);
- } catch (IllegalAccessException e) {
- throw Throwables.propagate(e);
- }
- }
-
- /** returns the default/inital value that is assigned to fields of the givien type;
- * if the type is not primitive this value is null;
- * for primitive types it is obvious but not AFAIK programmatically visible
- * (e.g. 0 for int, false for boolean)
- */
- public static Object getDefaultValueForType(Class<?> t) {
- if (!t.isPrimitive()) return null;
- if (t==Integer.TYPE) return (int)0;
- if (t==Long.TYPE) return (long)0;
- if (t==Double.TYPE) return (double)0;
- if (t==Float.TYPE) return (float)0;
- if (t==Byte.TYPE) return (byte)0;
- if (t==Short.TYPE) return (short)0;
- if (t==Character.TYPE) return (char)0;
- if (t==Boolean.TYPE) return false;
- //should never happen
- throw new IllegalStateException("Class "+t+" is an unknown primitive.");
- }
-
- /** returns a map of all fields which are annotated 'SetFromFlag', along with the annotation */
- public static Map<Field,SetFromFlag> getAnnotatedFields(Class<?> type) {
- Map<Field, SetFromFlag> result = Maps.newLinkedHashMap();
- for (Field f: getAllFields(type)) {
- SetFromFlag cf = f.getAnnotation(SetFromFlag.class);
- if (truth(cf)) result.put(f, cf);
- }
- return result;
- }
-
- /** returns a map of all {@link ConfigKey} fields which are annotated 'SetFromFlag', along with the annotation */
- public static Map<ConfigKey<?>,SetFromFlag> getAnnotatedConfigKeys(Class<?> type) {
- Map<ConfigKey<?>, SetFromFlag> result = Maps.newLinkedHashMap();
- List<Field> fields = getAllFields(type, new Predicate<Field>() {
- @Override public boolean apply(Field f) {
- return (f != null) && ConfigKey.class.isAssignableFrom(f.getType()) && ((f.getModifiers() & Modifier.STATIC)!=0);
- }});
- for (Field f: fields) {
- SetFromFlag cf = f.getAnnotation(SetFromFlag.class);
- if (cf != null) {
- ConfigKey<?> key = getFieldAsConfigKey(null, f);
- if (key != null) {
- result.put(key, cf);
- }
- }
- }
- return result;
- }
-
- /** returns a map of all fields which are annotated 'SetFromFlag' with their current values;
- * useful if you want to clone settings from one object
- */
- public static Map<String,Object> getFieldsWithValues(Object o) {
- try {
- Map<String, Object> result = Maps.newLinkedHashMap();
- for (Map.Entry<Field, SetFromFlag> entry : getAnnotatedFields(o.getClass()).entrySet()) {
- Field f = entry.getKey();
- SetFromFlag cf = entry.getValue();
- String flagName = elvis(cf.value(), f.getName());
- if (truth(flagName)) {
- if (!f.isAccessible()) f.setAccessible(true);
- result.put(flagName, f.get(o));
- }
- }
- return result;
- } catch (IllegalAccessException e) {
- throw Throwables.propagate(e);
- }
- }
-
- /**
- * @throws an IllegalStateException if there are fields required (nullable=false) which are unset
- * @throws wrapped IllegalAccessException
- */
- public static void checkRequiredFields(Object o) {
- try {
- Set<String> unsetFields = Sets.newLinkedHashSet();
- for (Map.Entry<Field, SetFromFlag> entry : getAnnotatedFields(o.getClass()).entrySet()) {
- Field f = entry.getKey();
- SetFromFlag cf = entry.getValue();
- if (!cf.nullable()) {
- String flagName = elvis(cf.value(), f.getName());
- if (!f.isAccessible()) f.setAccessible(true);
- Object v = f.get(o);
- if (v==null) unsetFields.add(flagName);
- }
- }
- if (truth(unsetFields)) {
- throw new IllegalStateException("Missing required "+(unsetFields.size()>1 ? "fields" : "field")+": "+unsetFields);
- }
- } catch (IllegalAccessException e) {
- throw Throwables.propagate(e);
- }
- }
-
-// /** sets all fields in target annotated with @SetFromFlag using the configuration in the given config bag */
-// public static void setFieldsFromConfigFlags(Object target, ConfigBag configBag) {
-// setFieldsFromConfigFlags(target, configBag.getAllConfig(), configBag);
-// }
-//
-//
-// /** sets all fields in target annotated with @SetFromFlag using the configuration in the given configToUse,
-// * marking used in the given configBag */
-// public static void setFieldsFromConfigFlags(Object target, Map<?,?> configToUse, ConfigBag configBag) {
-// for (Map.Entry<?,?> entry: configToUse.entrySet()) {
-// setFieldFromConfigFlag(target, entry.getKey(), entry.getValue(), configBag);
-// }
-// }
-//
-// public static void setFieldFromConfigFlag(Object target, Object key, Object value, ConfigBag optionalConfigBag) {
-// String name = null;
-// if (key instanceof String) name = (String)key;
-// else if (key instanceof ConfigKey<?>) name = ((ConfigKey<?>)key).getName();
-// else if (key instanceof HasConfigKey<?>) name = ((HasConfigKey<?>)key).getConfigKey().getName();
-// else {
-// if (key!=null) {
-// log.warn("Invalid config type "+key.getClass().getCanonicalName()+" ("+key+") when configuring "+target+"; ignoring");
-// }
-// return;
-// }
-// if (setFieldFromFlag(name, value, target)) {
-// if (optionalConfigBag!=null)
-// optionalConfigBag.markUsed(name);
-// }
-// }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/699b3f65/core/src/main/java/brooklyn/util/flags/MethodCoercions.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/flags/MethodCoercions.java b/core/src/main/java/brooklyn/util/flags/MethodCoercions.java
deleted file mode 100644
index c9f00fe..0000000
--- a/core/src/main/java/brooklyn/util/flags/MethodCoercions.java
+++ /dev/null
@@ -1,183 +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.flags;
-
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.guava.Maybe;
-import com.google.common.base.Optional;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Iterables;
-import com.google.common.reflect.TypeToken;
-
-import javax.annotation.Nullable;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Type;
-import java.util.Arrays;
-import java.util.List;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * A way of binding a loosely-specified method call into a strongly-typed Java method call.
- */
-public class MethodCoercions {
-
- /**
- * Returns a predicate that matches a method with the given name, and a single parameter that
- * {@link brooklyn.util.flags.TypeCoercions#tryCoerce(Object, com.google.common.reflect.TypeToken)} can process
- * from the given argument.
- *
- * @param methodName name of the method
- * @param argument argument that is intended to be given
- * @return a predicate that will match a compatible method
- */
- public static Predicate<Method> matchSingleParameterMethod(final String methodName, final Object argument) {
- checkNotNull(methodName, "methodName");
- checkNotNull(argument, "argument");
-
- return new Predicate<Method>() {
- @Override
- public boolean apply(@Nullable Method input) {
- if (input == null) return false;
- if (!input.getName().equals(methodName)) return false;
- Type[] parameterTypes = input.getGenericParameterTypes();
- return parameterTypes.length == 1
- && TypeCoercions.tryCoerce(argument, TypeToken.of(parameterTypes[0])).isPresentAndNonNull();
-
- }
- };
- }
-
- /**
- * Tries to find a single-parameter method with a parameter compatible with (can be coerced to) the argument, and
- * invokes it.
- *
- * @param instance the object to invoke the method on
- * @param methodName the name of the method to invoke
- * @param argument the argument to the method's parameter.
- * @return the result of the method call, or {@link brooklyn.util.guava.Maybe#absent()} if method could not be matched.
- */
- public static Maybe<?> tryFindAndInvokeSingleParameterMethod(final Object instance, final String methodName, final Object argument) {
- Class<?> clazz = instance.getClass();
- Iterable<Method> methods = Arrays.asList(clazz.getMethods());
- Optional<Method> matchingMethod = Iterables.tryFind(methods, matchSingleParameterMethod(methodName, argument));
- if (matchingMethod.isPresent()) {
- Method method = matchingMethod.get();
- try {
- Type paramType = method.getGenericParameterTypes()[0];
- Object coercedArgument = TypeCoercions.coerce(argument, TypeToken.of(paramType));
- return Maybe.of(method.invoke(instance, coercedArgument));
- } catch (IllegalAccessException | InvocationTargetException e) {
- throw Exceptions.propagate(e);
- }
- } else {
- return Maybe.absent();
- }
- }
-
- /**
- * Returns a predicate that matches a method with the given name, and parameters that
- * {@link brooklyn.util.flags.TypeCoercions#tryCoerce(Object, com.google.common.reflect.TypeToken)} can process
- * from the given list of arguments.
- *
- * @param methodName name of the method
- * @param arguments arguments that is intended to be given
- * @return a predicate that will match a compatible method
- */
- public static Predicate<Method> matchMultiParameterMethod(final String methodName, final List<?> arguments) {
- checkNotNull(methodName, "methodName");
- checkNotNull(arguments, "arguments");
-
- return new Predicate<Method>() {
- @Override
- public boolean apply(@Nullable Method input) {
- if (input == null) return false;
- if (!input.getName().equals(methodName)) return false;
- int numOptionParams = arguments.size();
- Type[] parameterTypes = input.getGenericParameterTypes();
- if (parameterTypes.length != numOptionParams) return false;
-
- for (int paramCount = 0; paramCount < numOptionParams; paramCount++) {
- if (!TypeCoercions.tryCoerce(((List) arguments).get(paramCount),
- TypeToken.of(parameterTypes[paramCount])).isPresentAndNonNull()) return false;
- }
- return true;
- }
- };
- }
-
- /**
- * Tries to find a multiple-parameter method with each parameter compatible with (can be coerced to) the
- * corresponding argument, and invokes it.
- *
- * @param instance the object to invoke the method on
- * @param methodName the name of the method to invoke
- * @param argument a list of the arguments to the method's parameters.
- * @return the result of the method call, or {@link brooklyn.util.guava.Maybe#absent()} if method could not be matched.
- */
- public static Maybe<?> tryFindAndInvokeMultiParameterMethod(final Object instance, final String methodName, final List<?> arguments) {
- Class<?> clazz = instance.getClass();
- Iterable<Method> methods = Arrays.asList(clazz.getMethods());
- Optional<Method> matchingMethod = Iterables.tryFind(methods, matchMultiParameterMethod(methodName, arguments));
- if (matchingMethod.isPresent()) {
- Method method = matchingMethod.get();
- try {
- int numOptionParams = ((List)arguments).size();
- Object[] coercedArguments = new Object[numOptionParams];
- for (int paramCount = 0; paramCount < numOptionParams; paramCount++) {
- Object argument = arguments.get(paramCount);
- Type paramType = method.getGenericParameterTypes()[paramCount];
- coercedArguments[paramCount] = TypeCoercions.coerce(argument, TypeToken.of(paramType));
- }
- return Maybe.of(method.invoke(instance, coercedArguments));
- } catch (IllegalAccessException | InvocationTargetException e) {
- throw Exceptions.propagate(e);
- }
- } else {
- return Maybe.absent();
- }
- }
-
- /**
- * Tries to find a method with each parameter compatible with (can be coerced to) the corresponding argument, and invokes it.
- *
- * @param instance the object to invoke the method on
- * @param methodName the name of the method to invoke
- * @param argument a list of the arguments to the method's parameters, or a single argument for a single-parameter method.
- * @return the result of the method call, or {@link brooklyn.util.guava.Maybe#absent()} if method could not be matched.
- */
- public static Maybe<?> tryFindAndInvokeBestMatchingMethod(final Object instance, final String methodName, final Object argument) {
- if (argument instanceof List) {
- List<?> arguments = (List<?>) argument;
-
- // ambiguous case: we can't tell if the user is using the multi-parameter syntax, or the single-parameter
- // syntax for a method which takes a List parameter. So we try one, then fall back to the other.
-
- Maybe<?> maybe = tryFindAndInvokeMultiParameterMethod(instance, methodName, arguments);
- if (maybe.isAbsent())
- maybe = tryFindAndInvokeSingleParameterMethod(instance, methodName, argument);
-
- return maybe;
- } else {
- return tryFindAndInvokeSingleParameterMethod(instance, methodName, argument);
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/699b3f65/core/src/main/java/brooklyn/util/flags/SetFromFlag.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/flags/SetFromFlag.java b/core/src/main/java/brooklyn/util/flags/SetFromFlag.java
deleted file mode 100644
index c7d588e..0000000
--- a/core/src/main/java/brooklyn/util/flags/SetFromFlag.java
+++ /dev/null
@@ -1,71 +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.flags;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Annotation to indicate that a variable may be set through the use of a named argument,
- * looking for the name specified here or inferred from the annotated field/argument/object.
- * <p>
- * This is used to automate the processing where named arguments are passed in constructors
- * and other methods, and the values of those named arguments should be transferred to
- * other known fields/arguments/objects at runtime.
- * <p>
- * Fields on a class are typically set from values in a map with a call to
- * {@link FlagUtils#setFieldsFromFlags(java.util.Map, Object)}.
- * That method (and related, in the same class) will attend to the arguments here.
- */
-@Retention(RetentionPolicy.RUNTIME)
-public @interface SetFromFlag {
-
- /** the flag (key) which should be used to find the value; if empty defaults to field/argument/object name */
- String value() default "";
-
- /** whether the object should not be changed once set; defaults to false
- * <p>
- * this is partially tested for in many routines, but not all;
- * when nullable=false the testing (when done) is guaranteed.
- * however if nullable is allowed we do not distinguish between null and unset
- * so explicitly setting null then setting to a value is not detected as an illegal mutating.
- */
- boolean immutable() default false;
-
- /** whether the object is required & should not be set to null; defaults to true.
- * (there is no 'required' parameter, but setting nullable false then invoking
- * e.g. {@link FlagUtils#checkRequiredFields(Object)} has the effect of requiring a value)
- * <p>
- * code should call that method explicitly to enforce nullable false;
- * errors are not done during a call to setFieldsFromFlags
- * because fields may be initialised in multiple passes.)
- * <p>
- * this is partially tested for in many routines, but not all
- */
- boolean nullable() default true;
-
- /** The default value, if it is not explicitly set.
- * <p>
- * The value will be coerced from String where required, for types supported by {@link TypeCoercions}.
- * <p>
- * The field will be initialised with its default value on the first call to setFieldsFromFlags
- * (or related). (The field will not be initialised if that method is not called.)
- */
- String defaultVal() default "";
-}