Java Code Examples for org.apache.brooklyn.util.text.Strings#isNonBlank()

The following examples show how to use org.apache.brooklyn.util.text.Strings#isNonBlank() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: BasicBrooklynCatalog.java    From brooklyn-server with Apache License 2.0 6 votes vote down vote up
/**
 * @deprecated since 1.0.0; Catalog annotation is deprecated.
 */
@Deprecated
private Collection<CatalogItemDtoAbstract<?, ?>> scanAnnotationsLegacyInListOfLibraries(ManagementContext mgmt, Collection<? extends OsgiBundleWithUrl> libraries, Map<?, ?> catalogMetadata, ManagedBundle containingBundle) {
    CatalogDto dto = CatalogDto.newNamedInstance("Bundles Scanned Catalog", "All annotated Brooklyn entities detected in bundles", "scanning-bundles-classpath-"+libraries.hashCode());
    List<String> urls = MutableList.of();
    for (OsgiBundleWithUrl b: libraries) {
        // does not support pre-installed bundles identified by name:version 
        // (ie where URL not supplied)
        if (Strings.isNonBlank(b.getUrl())) {
            urls.add(b.getUrl());
        } else {
            log.warn("scanJavaAnnotations does not apply to pre-installed bundles; skipping "+b);
        }
    }
    
    if (urls.isEmpty()) {
        log.warn("No bundles to scan: scanJavaAnnotations currently only applies to OSGi bundles provided by URL"); 
        return MutableList.of();
    }
    
    CatalogDo subCatalog = new CatalogDo(dto);
    subCatalog.addToClasspath(urls.toArray(new String[0]));
    return scanAnnotationsInternal(mgmt, subCatalog, catalogMetadata, containingBundle);
}
 
Example 2
Source File: InternalEntityFactory.java    From brooklyn-server with Apache License 2.0 6 votes vote down vote up
private void addSpecParameters(EntitySpec<?> spec, EntityDynamicType edType) {
    // if coming from a catalog item, parsed by CAMP, then the spec list of parameters is canonical,
    // the parent item has had its config keys set as parameters here with those non-inheritable
    // via type definition removed, so wipe those on the EDT to make sure non-inheritable ones are removed;
    // OTOH if item is blank, it was set as a java type, not inheriting it,
    // and the config keys on the dynamic type are the correct ones to use, and usually there is nothing in spec.parameters,
    // except what is being added programmatically.
    // (this logic could get confused if catalog item ID referred to some runtime-inherited context,
    // but those semantics should no longer be used -- https://issues.apache.org/jira/browse/BROOKLYN-445)
    if (Strings.isNonBlank(spec.getCatalogItemId())) {
        edType.clearConfigKeys();
    }
    for (SpecParameter<?> param : spec.getParameters()) {
        edType.addConfigKey(param.getConfigKey());
        if (param.getSensor()!=null) edType.addSensor(param.getSensor());
    }
}
 
Example 3
Source File: Main.java    From brooklyn-server with Apache License 2.0 6 votes vote down vote up
protected PersistMode computePersistMode() {
    Maybe<PersistMode> persistMode = Enums.valueOfIgnoreCase(PersistMode.class, persist);
    if (!persistMode.isPresent()) {
        if (Strings.isBlank(persist)) {
            throw new FatalConfigurationRuntimeException("Persist mode must not be blank");
        } else {
            throw new FatalConfigurationRuntimeException("Illegal persist setting: "+persist);
        }
    }
   
    if (persistMode.get() == PersistMode.DISABLED) {
        if (Strings.isNonBlank(persistenceDir))
            throw new FatalConfigurationRuntimeException("Cannot specify persistenceDir when persist is disabled");
        if (Strings.isNonBlank(persistenceLocation))
            throw new FatalConfigurationRuntimeException("Cannot specify persistenceLocation when persist is disabled");
    }
    return persistMode.get();
}
 
Example 4
Source File: BasicLauncher.java    From brooklyn-server with Apache License 2.0 6 votes vote down vote up
private void startPersistenceWithoutHA() {
    RebindManager rebindManager = managementContext.getRebindManager();
    if (Strings.isNonBlank(persistenceLocation))
        LOG.info("Management node (no HA) rebinding to entities at "+persistenceLocation+" in "+persistenceDir);
    else
        LOG.info("Management node (no HA) rebinding to entities on file system in "+persistenceDir);

    ClassLoader classLoader = managementContext.getCatalogClassLoader();
    try {
        rebindManager.rebind(classLoader, null, ManagementNodeState.MASTER);
    } catch (Exception e) {
        Exceptions.propagateIfFatal(e);
        LOG.debug("Error rebinding to persisted state (rethrowing): "+e, e);
        throw new FatalRuntimeException("Error rebinding to persisted state: "+
            Exceptions.collapseText(e), e);
    }
    rebindManager.startPersistence();
}
 
Example 5
Source File: JcloudsLocation.java    From brooklyn-server with Apache License 2.0 6 votes vote down vote up
/** @return An Iterable of credentials based on nodeCreds containing different parameters. */
Iterable<LoginCredentials> generateCredentials(LoginCredentials nodeCreds, @Nullable String loginUserOverride) {
    String nodeUser = nodeCreds.getUser();
    Set<String> users = MutableSet.of();
    if (Strings.isNonBlank(nodeUser)) {
        users.add(nodeUser);
    }
    if (Strings.isNonBlank(loginUserOverride)) {
        users.add(loginUserOverride);
    }
    List<LoginCredentials> credentialsToTry = new ArrayList<>();
    for (String user : users) {
        if (nodeCreds.getOptionalPassword().isPresent() && nodeCreds.getOptionalPrivateKey().isPresent()) {
            credentialsToTry.add(LoginCredentials.builder(nodeCreds).noPassword().user(user).build());
            credentialsToTry.add(LoginCredentials.builder(nodeCreds).noPrivateKey().user(user).build());
        } else {
            credentialsToTry.add(LoginCredentials.builder(nodeCreds).user(user).build());
        }
    }
    return credentialsToTry;
}
 
Example 6
Source File: Entitlements.java    From brooklyn-server with Apache License 2.0 6 votes vote down vote up
public static EntitlementManager load(@Nullable ManagementContext mgmt, BrooklynProperties brooklynProperties, String type) {
    if ("root".equalsIgnoreCase(type)) {
        return root();
    } else if ("readonly".equalsIgnoreCase(type) || "read_only".equalsIgnoreCase(type)) {
        return readOnly();
    } else if ("minimal".equalsIgnoreCase(type)) {
        return minimal();
    } else if ("user".equalsIgnoreCase(type)) {
        return user();
    }
    if (Strings.isNonBlank(type)) {
        try {
            Class<?> clazz = new ClassLoaderUtils(Entitlements.class, mgmt).loadClass(DeserializingClassRenamesProvider.INSTANCE.findMappedName(type));
            return (EntitlementManager) instantiate(clazz, ImmutableList.of(
                    new Object[] {mgmt, brooklynProperties},
                    new Object[] {mgmt},
                    new Object[] {brooklynProperties},
                    new Object[0]));
        } catch (Exception e) { 
            throw Exceptions.propagate(e); 
        }
    }
    throw new IllegalStateException("Invalid entitlement manager specified: '"+type+"'");
}
 
Example 7
Source File: BundleMaker.java    From brooklyn-server with Apache License 2.0 5 votes vote down vote up
/** true iff given ZIP/JAR file contains a MANIFEST.MF file defining a bundle symbolic name */
public boolean hasOsgiManifest(File f) {
    Manifest mf = getManifest(f);
    if (mf==null) return false;
    String sn = mf.getMainAttributes().getValue(Constants.BUNDLE_SYMBOLICNAME);
    return Strings.isNonBlank(sn);
}
 
Example 8
Source File: AbstractEntity.java    From brooklyn-server with Apache License 2.0 5 votes vote down vote up
/**
 * Default entity initialization sets ID sensors and calls {@link #initEnrichers()}.
 */
@Override
public void init() {
    super.init();
    initEnrichers();
    if (Strings.isNonBlank(getConfig(DEFAULT_DISPLAY_NAME))) {
        setDefaultDisplayName(getConfig(DEFAULT_DISPLAY_NAME));
    }
    sensors().set(ENTITY_ID, getId());
    sensors().set(APPLICATION_ID, getApplicationId());
    sensors().set(CATALOG_ID, getCatalogItemId());
}
 
Example 9
Source File: AbstractSoftwareProcessWinRmDriver.java    From brooklyn-server with Apache License 2.0 5 votes vote down vote up
@Override
public void runPostLaunchCommand() {
    if (Strings.isNonBlank(entity.getConfig(BrooklynConfigKeys.POST_LAUNCH_COMMAND)) || Strings.isNonBlank(entity.getConfig(VanillaWindowsProcess.POST_LAUNCH_POWERSHELL_COMMAND))) {
        executeCommandInTask(
                getEntity().getConfig(BrooklynConfigKeys.POST_LAUNCH_COMMAND),
                getEntity().getConfig(VanillaWindowsProcess.POST_LAUNCH_POWERSHELL_COMMAND),
                AbstractSoftwareProcessSshDriver.LAUNCHING,
                "post-launch-command");
    }
}
 
Example 10
Source File: ApiError.java    From brooklyn-server with Apache License 2.0 5 votes vote down vote up
/** puts a prefix in front of the message, with the given separator if there is already a message;
 * if there is no message, it simply sets the prefix as the message.
 * if no prefix or blank, does nothing.
 */
public Builder prefixMessage(String prefix, String separatorIfMessageNotBlank) {
    if (Strings.isNonBlank(prefix)) {
        if (Strings.isBlank(message)) message(prefix);
        else message(prefix+separatorIfMessageNotBlank+message);
    }
    return this;
}
 
Example 11
Source File: SetHostnameCustomizer.java    From brooklyn-server with Apache License 2.0 5 votes vote down vote up
/**
 * Sets the machine's hostname to the given value, ensuring /etc/hosts and /etc/sysconfig/network are both 
 * correctly updated.
 */
public String setLocalHostname(SshMachineLocation machine, String hostName, String domainFixed) {
    log.info("Setting local hostname of " + machine + " to " + hostName 
            + (Strings.isNonBlank(domainFixed) ? ", " + domainFixed : ""));
    
    boolean hasDomain = Strings.isNonBlank(domainFixed);
    String fqdn = hasDomain ? hostName+"."+domainFixed : hostName;
    
    exec(machine, true, 
            BashCommands.sudo(String.format("sed -i.bak -e '1i127.0.0.1 %s %s' -e '/^127.0.0.1/d' /etc/hosts", fqdn, hostName)),
            BashCommands.sudo(String.format("sed -i.bak -e 's/^HOSTNAME=.*$/HOSTNAME=%s/' /etc/sysconfig/network", fqdn)),
            BashCommands.sudo(String.format("hostname %s", fqdn)));

    return hostName;
}
 
Example 12
Source File: AbstractSoftwareProcessWinRmDriver.java    From brooklyn-server with Apache License 2.0 5 votes vote down vote up
@Override
public void runPreCustomizeCommand() {
    if (Strings.isNonBlank(getEntity().getConfig(BrooklynConfigKeys.PRE_CUSTOMIZE_COMMAND)) || Strings.isNonBlank(getEntity().getConfig(VanillaWindowsProcess.PRE_CUSTOMIZE_POWERSHELL_COMMAND))) {
        executeCommandInTask(
                getEntity().getConfig(BrooklynConfigKeys.PRE_CUSTOMIZE_COMMAND),
                getEntity().getConfig(VanillaWindowsProcess.PRE_CUSTOMIZE_POWERSHELL_COMMAND),
                AbstractSoftwareProcessSshDriver.CUSTOMIZING,
                "pre-customize-command");
    }
}
 
Example 13
Source File: AbstractSoftwareProcessSshDriver.java    From brooklyn-server with Apache License 2.0 5 votes vote down vote up
private void executeSuccessfully(ConfigKey<String> configKey, String label) {
    if(Strings.isNonBlank(getEntity().getConfig(configKey))) {
        log.debug("Executing {} on entity {}", label, entity.getDisplayName());
        int result = execute(ImmutableList.of(getEntity().getConfig(configKey)), label);
        if (0 != result) {
            log.debug("Executing {} failed with return code {}", label, result);
            throw new IllegalStateException("commands for " + configKey.getName() + " failed with return code " + result);
        }
    }
}
 
Example 14
Source File: VanillaSoftwareProcessSshDriver.java    From brooklyn-server with Apache License 2.0 5 votes vote down vote up
@Override
public void launch() {
    String launchCommand = getEntity().getConfig(VanillaSoftwareProcess.LAUNCH_COMMAND);
    
    if (Strings.isNonBlank(launchCommand)) {
        newScript(LAUNCHING)
            .failOnNonZeroResultCode()
            .body.append(launchCommand)
            .execute();
    }
}
 
Example 15
Source File: BashCommands.java    From brooklyn-server with Apache License 2.0 4 votes vote down vote up
/**
 * Sets the hostname to {@code hostPart + "." + domainPart}, or if domainPart is null/empty then {code hostPart}.
 * 
 * @param hostPart
 * @param domainPart
 * @return
 */
@Beta
public static List<String> setHostname(String hostPart, String domainPart) {
    // See:
    // - http://www.rackspace.com/knowledge_center/article/centos-hostname-change
    // - https://wiki.debian.org/HowTo/ChangeHostname
    // - http://askubuntu.com/questions/9540/how-do-i-change-the-computer-name
    //
    // We prepend in /etc/hosts, to ensure the right fqn appears first.
    //    e.g. comment in http://askubuntu.com/questions/158957/how-to-set-the-fully-qualified-domain-name-in-12-04
    //    says "It's important to note that the first domain in /etc/hosts should be your FQDN. "
    //
    // TODO Should we run `sudo service hostname restart` or `sudo /etc/init.d/hostname restart`?
    //      I don't think we need to because we've run `sudo hostname <newname>`
    //
    // TODO What if /etc/sysconfig/network doesn't have a line for HOSTNAME=...?
    //
    // TODO What about hostPart ending in "." - see http://www.dns-sd.org/trailingdotsindomainnames.html
    //      for what that means in DNS. However, hostname is not the same as the DNS name (hostnames 
    //      predate the invention of DNS! - although frequently the DNS name has the same first portion 
    //      as the hostname) so the link you gave is not relevant. However despite searching Google and 
    //      man pages I [Ricard] am unable to find a reference which clearly states what characters are 
    //      relevant in a hostname. I think it's safest to assume that the hostname is just [a-z,0-9,-] 
    //      and no dots at all.
    
    checkNotNull(hostPart, "hostPart");
    checkArgument(!hostPart.contains("."), "hostPart '%s' must not contain '.'", hostPart);

    String tempFileId = "bak"+Identifiers.makeRandomId(4);
    
    List<String> allhostnames = Lists.newArrayList();
    String fqdn = hostPart;
    if (Strings.isNonBlank(domainPart)) {
        fqdn = hostPart+"."+domainPart;
        allhostnames.add(fqdn);
    }
    allhostnames.add(hostPart);
    allhostnames.add("localhost");
    
    return ImmutableList.of(
            sudo("sed -i."+tempFileId+" -e 's/^127.0.0.1/# Replaced by Brooklyn\\\n#127.0.0.1/' /etc/hosts"),
            prependToEtcHosts("127.0.0.1", allhostnames.toArray(new String[allhostnames.size()])),
            ifFileExistsElse0("/etc/sysconfig/network", sudo("sed -i."+tempFileId+" -e 's/^HOSTNAME=.*$/HOSTNAME="+hostPart+"/' /etc/sysconfig/network")),
            ifFileExistsElse0("/etc/hostname", sudo("sed -i."+tempFileId+" -e 's/^[a-zA-Z_0-9].*$/"+hostPart+"/' /etc/hostname")),
            sudo("hostname "+hostPart));
}
 
Example 16
Source File: RiakNodeSshDriver.java    From brooklyn-library with Apache License 2.0 4 votes vote down vote up
@Override
public void customize() {
    checkRiakOnPath();

    //create entity's runDir
    newScript(CUSTOMIZING).execute();

    OsDetails osDetails = getMachine().getMachineDetails().getOsDetails();

    List<String> commands = Lists.newLinkedList();
    commands.add(sudo("mkdir -p " + getRiakEtcDir()));

    if (isVersion1()) {
        String vmArgsTemplate = processTemplate(entity.getConfig(RiakNode.RIAK_VM_ARGS_TEMPLATE_URL));
        String saveAsVmArgs = Urls.mergePaths(getRunDir(), "vm.args");
        DynamicTasks.queue(SshEffectorTasks.put(saveAsVmArgs).contents(vmArgsTemplate));
        commands.add(sudo("mv " + saveAsVmArgs + " " + getRiakEtcDir()));

        String appConfigTemplate = processTemplate(entity.getConfig(RiakNode.RIAK_APP_CONFIG_TEMPLATE_URL));
        String saveAsAppConfig = Urls.mergePaths(getRunDir(), "app.config");
        DynamicTasks.queue(SshEffectorTasks.put(saveAsAppConfig).contents(appConfigTemplate));
        commands.add(sudo("mv " + saveAsAppConfig + " " + getRiakEtcDir()));
    } else {
        String templateUrl = osDetails.isMac() ? entity.getConfig(RiakNode.RIAK_CONF_TEMPLATE_URL_MAC) :
                entity.getConfig(RiakNode.RIAK_CONF_TEMPLATE_URL_LINUX);
        String riakConfContent = processTemplate(templateUrl);
        String saveAsRiakConf = Urls.mergePaths(getRunDir(), "riak.conf");

        if(Strings.isNonBlank(entity.getConfig(RiakNode.RIAK_CONF_ADDITIONAL_CONTENT))) {
            String additionalConfigContent = processTemplateContents(entity.getConfig(RiakNode.RIAK_CONF_ADDITIONAL_CONTENT));
            riakConfContent += "\n## Brooklyn note: additional config\n";
            riakConfContent += additionalConfigContent;
        }

        DynamicTasks.queue(SshEffectorTasks.put(saveAsRiakConf).contents(riakConfContent));
        commands.add(sudo("mv " + saveAsRiakConf + " " + getRiakEtcDir()));
    }

    //increase open file limit (default min for riak is: 4096)
    //TODO: detect the actual limit then do the modification.
    //TODO: modify ulimit for linux distros
    //    commands.add(sudo("launchctl limit maxfiles 4096 32768"));
    if (osDetails.isMac()) {
        commands.add("ulimit -n 4096");
    }

    if (osDetails.isLinux() && isVersion1()) {
        commands.add(sudo("chown -R riak:riak " + getRiakEtcDir()));
    }

    // TODO platform_*_dir
    // TODO riak config log

    ScriptHelper customizeScript = newScript(CUSTOMIZING)
            .failOnNonZeroResultCode()
            .body.append(commands);

    if (!isRiakOnPath()) {
        addRiakOnPath(customizeScript);
    }
    customizeScript.failOnNonZeroResultCode().execute();

    if (osDetails.isLinux()) {
        ImmutableMap<String, String> sysctl = ImmutableMap.<String, String>builder()
                .put("vm.swappiness", "0")
                .put("net.core.somaxconn", "40000")
                .put("net.ipv4.tcp_max_syn_backlog", "40000")
                .put("net.ipv4.tcp_sack",  "1")
                .put("net.ipv4.tcp_window_scaling",  "15")
                .put("net.ipv4.tcp_fin_timeout",     "1")
                .put("net.ipv4.tcp_keepalive_intvl", "30")
                .put("net.ipv4.tcp_tw_reuse",        "1")
                .put("net.ipv4.tcp_moderate_rcvbuf", "1")
                .build();

        ScriptHelper optimize = newScript(CUSTOMIZING + "network")
            .body.append(sudo("sysctl " + Joiner.on(' ').withKeyValueSeparator("=").join(sysctl)));

        Optional<Boolean> enable = Optional.fromNullable(entity.getConfig(RiakNode.OPTIMIZE_HOST_NETWORKING));
        if (!enable.isPresent()) optimize.inessential();
        if (enable.or(true)) optimize.execute();
    }

    //set the riak node name
    entity.sensors().set(RiakNode.RIAK_NODE_NAME, format("riak@%s", getSubnetHostname()));
}
 
Example 17
Source File: LocationResource.java    From brooklyn-server with Apache License 2.0 4 votes vote down vote up
private static String getNameOrSpec(LocationSummary o) {
    if (Strings.isNonBlank(o.getName())) return o.getName();
    if (Strings.isNonBlank(o.getSpec())) return o.getSpec();
    return o.getId();
}
 
Example 18
Source File: XmlMementoSerializer.java    From brooklyn-server with Apache License 2.0 4 votes vote down vote up
@Override
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
    String catalogItemId = null;
    instantiateNewInstanceSettingCache(reader, context);
    
    if (reader instanceof PathTrackingReader) {
        // have to assume this is first; there is no mark/reset support on these readers
        // (if there were then it would be easier, we could just look for that child anywhere,
        // and not need a custom writer!)
        if ("catalogItemId".equals( ((PathTrackingReader)reader).peekNextChild() )) {
            // cache the instance
            
            reader.moveDown();
            catalogItemId = reader.getValue();
            reader.moveUp();
        }
    }
    boolean customLoaderSet = false;
    try {
        if (Strings.isNonBlank(catalogItemId)) {
            if (lookupContext==null) throw new NullPointerException("lookupContext required to load catalog item "+catalogItemId);
            RegisteredType cat = lookupContext.lookupManagementContext().getTypeRegistry().get(catalogItemId);
            if (cat==null) {
                String upgradedItemId = CatalogUpgrades.getTypeUpgradedIfNecessary(lookupContext.lookupManagementContext(), catalogItemId);
                if (!Objects.equal(catalogItemId, upgradedItemId)) {
                    LOG.warn("Upgrading spec catalog item id from "+catalogItemId+" to "+upgradedItemId+" on rebind "+getContextDescription(context));
                    cat = lookupContext.lookupManagementContext().getTypeRegistry().get(upgradedItemId);
                    catalogItemId = upgradedItemId;
                }
            }
            if (cat==null) throw new NoSuchElementException("catalog item: "+catalogItemId);
            BrooklynClassLoadingContext clcNew = CatalogUtils.newClassLoadingContext(lookupContext.lookupManagementContext(), cat);
            delegatingClassLoader.pushClassLoadingContext(clcNew);
            customLoaderSet = true;
            
            CatalogUpgrades.markerForCodeThatLoadsJavaTypesButShouldLoadRegisteredType();
        }
        
        AbstractBrooklynObjectSpec<?, ?> result = (AbstractBrooklynObjectSpec<?, ?>) super.unmarshal(reader, context);
        // we wrote it twice so this shouldn't be necessary; but if we fix it so we only write once, we'd need this
        result.catalogItemId(catalogItemId);
        return result;
    } finally {
        context.put("SpecConverter.instance", null);
        if (customLoaderSet) {
            delegatingClassLoader.popClassLoadingContext();
        }
    }
}
 
Example 19
Source File: BashCommands.java    From brooklyn-server with Apache License 2.0 4 votes vote down vote up
public static String unzip(String file, String targetDir) {
    return "unzip " + file + (Strings.isNonBlank(targetDir) ? " -d "+targetDir : "");
}
 
Example 20
Source File: Exceptions.java    From brooklyn-server with Apache License 2.0 4 votes vote down vote up
private static Throwable collapse(Throwable source, boolean collapseCausalChain, boolean includeAllCausalMessages, Set<Throwable> visited, Object contexts[]) {
    if (visited.isEmpty()) {
        if (isCausalChainDepthExceeding(source, MAX_COLLAPSE_RECURSIVE_DEPTH)) {
            // do fast check above, then do deeper check which survives recursive causes
            List<Throwable> chain = getCausalChain(source);
            if (chain.size() > MAX_COLLAPSE_RECURSIVE_DEPTH) {
                // if it's an OOME or other huge stack, shrink it so we don't spin huge cycles processing the trace and printing it
                // (sometimes generating subsequent OOME's in logback that mask the first!)
                // coarse heuristic for how to reduce it, but that's better than killing cpu, causing further errors, and suppressing the root cause altogether!
                String msg = chain.get(0).getMessage();
                if (msg.length() > 512) msg = msg.substring(0, 500)+"...";
                return new PropagatedRuntimeException("Huge stack trace (size "+chain.size()+", removing all but last few), "
                        + "starting: "+chain.get(0).getClass().getName()+": "+msg+"; ultimately caused by: ", 
                        chain.get(chain.size() - 10));
            }
        }
    }

    visited = MutableSet.copyOf(visited);
    String message = "";
    Throwable collapsed = source;
    int collapseCount = 0;
    boolean messageIsFinal = false;
    // remove boring exceptions at the head; if message is interesting append it
    while ((isBoringForMessage(collapsed) || isSkippableInContext(collapsed, contexts)) && !messageIsFinal) {
        collapseCount++;
        Throwable cause = collapsed.getCause();
        if (cause==null) {
            // everything in the tree is boring...
            return source;
        }
        if (!visited.add(collapsed)) {
            // there is a recursive loop
            break;
        }
        String collapsedS = collapsed.getMessage();
        if (collapsed instanceof PropagatedRuntimeException && ((PropagatedRuntimeException)collapsed).isCauseEmbeddedInMessage()) {
            message = collapsedS;
            messageIsFinal = true;
        }
        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;
        }
        visited.add(messagesCause); messagesCause = messagesCause.getCause();
    }
    
    if (collapseCount==0 && !includeAllCausalMessages)
        return source;
    
    if (collapseCount==0 && messagesCause!=null) {
        message = getMessageWithAppropriatePrefix(messagesCause);
        messagesCause = messagesCause.getCause();
    }
    
    if (messagesCause!=null && !messageIsFinal) {
        String extraMessage = collapseText(messagesCause, includeAllCausalMessages, ImmutableSet.copyOf(visited), contexts);
        message = appendSeparator(message, extraMessage);
    }
    if (message==null) message = "";
    return new PropagatedRuntimeException(message, collapseCausalChain ? collapsed : source, Strings.isNonBlank(message));
}