protected String getConnectionSchemaName() {
        if (connection == null) {
            return null;
        }
        if (connection instanceof OfflineConnection) {
            return ((OfflineConnection) connection).getSchema();
        }

        try {
            SqlStatement currentSchemaStatement = getConnectionSchemaNameCallStatement();
            return ExecutorService.getInstance().getExecutor(this).
                    queryForObject(currentSchemaStatement, String.class);
        } catch (Exception e) {
            Scope.getCurrentScope().getLog(getClass()).info(LogType.LOG, "Error getting default schema", e);
        }
        return null;
    }

protected
String
getConnectionSchemaName
(
)
{
if
(
connection
==
)
{
return
;
}
if
(
connection
instanceof
OfflineConnection
)
{
return
(
(
OfflineConnection
)
connection
)
.
getSchema
(
)
;
}
try
{
SqlStatement
currentSchemaStatement
=
getConnectionSchemaNameCallStatement
(
)
;
return
ExecutorService
.
getInstance
(
)
.
getExecutor
(
this
)
.
queryForObject
(
currentSchemaStatement
,
String
.
class
)
;
}
catch
(
Exception
e
)
{
Scope
.
getCurrentScope
(
)
.
getLog
(
getClass
(
)
)
.
info
(
LogType
.
LOG
,
"Error getting default schema"
,
e
)
;
}
return
;
}

Overwrite this method to get the default schema name for the connection.
If you only need to change the statement that obtains the current schema then override
@see AbstractJdbcDatabase#getConnectionSchemaNameCallStatement()

Overwrite this method to get the default schema name for the connection . If you only need to change the statement that obtains the current schema then override


@Override
    public boolean isSafeToRunUpdate() throws DatabaseException {
        DatabaseConnection connection = getConnection();
        if (connection == null) {
            return true;
        }
        String url = connection.getURL();
        if (url == null) {
            return false;
        }
        return (url.contains("localhost")) || (url.contains("127.0.0.1"));
    }

@ Override public boolean isSafeToRunUpdate ( ) throws DatabaseException { DatabaseConnection connection = getConnection ( ) ; if ( connection == null ) { return true ; } String url = connection . getURL ( ) ; if ( url == null ) { return false ; } return ( url . contains ( "localhost" ) ) || ( url . contains ( "127.0.0.1" ) ) ; }

Default implementation, just look for "local" IPs. If the database returns a null URL we return false since we don't know it's safe to run the update.

@throws liquibase.exception.DatabaseException

Default implementation just look for local IPs . If the database returns a null URL we return false since we don t know it s safe to run the update .


protected List<SqlVisitor> filterRollbackVisitors(final List<SqlVisitor> visitors) {
        final List<SqlVisitor> rollbackVisitors = new ArrayList<>();
        if (visitors != null) {
            for (SqlVisitor visitor : visitors) {
                if (visitor.isApplyToRollback()) {
                    rollbackVisitors.add(visitor);
                }
            }
        }

        return rollbackVisitors;
    }

protected List < SqlVisitor > filterRollbackVisitors ( final List < SqlVisitor > visitors ) { final List < SqlVisitor > rollbackVisitors = new ArrayList <> ( ) ; if ( visitors != null ) { for ( SqlVisitor visitor : visitors ) { if ( visitor . isApplyToRollback ( ) ) { rollbackVisitors . add ( visitor ) ; } } } return rollbackVisitors ; }

Takes a list of SqlVisitors and returns a new list with only the SqlVisitors set to apply to rollbacks


@Override
    public int getMaxFractionalDigitsForTimestamp() {
        if (getConnection() == null) {
            // if no connection is there we cannot do anything...
            Scope.getCurrentScope().getLog(getClass()).warning(
                    LogType.LOG, "No database connection available - specified"
                            + " DATETIME/TIMESTAMP precision will be tried");
            return DEFAULT_MAX_TIMESTAMP_FRACTIONAL_DIGITS;
        }

        return DEFAULT_MAX_TIMESTAMP_FRACTIONAL_DIGITS;
    }

Most relational databases support 9 fractional digits, and subclasses must overwrite this method if they
support less than that.

@return the maxmimum number of supported fractional digits in TIMESTAMP columns

Most relational databases support 9 fractional digits and subclasses must overwrite this method if they support less than that .


protected String checkString(String text) throws UnexpectedLiquibaseException {
        if (null == text || text.isEmpty()) {
            return text;
        }

        final int len = text.length();
        char current;
        int codePoint;

        for (int i = 0; i < len; i++) {
            current = text.charAt(i);
            if (Character.isHighSurrogate(current) && i + 1 < len && Character.isLowSurrogate(text.charAt(i + 1))) {
                codePoint = text.codePointAt(i++);
            } else {
                codePoint = current;
            }
            if ((codePoint == '\n')
                    || (codePoint == '\r')
                    || (codePoint == '\t')
                    || (codePoint == 0xB)
                    || (codePoint == 0xC)
                    || ((codePoint >= 0x20) && (codePoint <= 0x7E))
                    || ((codePoint >= 0xA0) && (codePoint <= 0xD7FF))
                    || ((codePoint >= 0xE000) && (codePoint <= 0xFFFD))
                    || ((codePoint >= 0x10000) && (codePoint <= 0x10FFFF))
                    ) {
                //ok
            } else {
                throw new UnexpectedLiquibaseException(INVALID_STRING_ENCODING_MESSAGE);
            }
        }

        return text;
    }

protected String checkString ( String text ) throws UnexpectedLiquibaseException { if ( null == text || text . isEmpty ( ) ) { return text ; } final int len = text . length ( ) ; char current ; int codePoint ; for ( int i = 0 ; i < len ; i ++ ) { current = text . charAt ( i ) ; if ( Character . isHighSurrogate ( current ) && i + 1 < len && Character . isLowSurrogate ( text . charAt ( i + 1 ) ) ) { codePoint = text . codePointAt ( i ++ ) ; } else { codePoint = current ; } if ( ( codePoint == ' ' ) || ( codePoint == ' ' ) || ( codePoint == ' ' ) || ( codePoint == 0xB ) || ( codePoint == 0xC ) || ( ( codePoint >= 0x20 ) && ( codePoint <= 0x7E ) ) || ( ( codePoint >= 0xA0 ) && ( codePoint <= 0xD7FF ) ) || ( ( codePoint >= 0xE000 ) && ( codePoint <= 0xFFFD ) ) || ( ( codePoint >= 0x10000 ) && ( codePoint <= 0x10FFFF ) ) ) { //ok } else { throw new UnexpectedLiquibaseException ( INVALID_STRING_ENCODING_MESSAGE ) ; } } return text ; }

Catch any characters that will cause problems when parsing the XML down the road.

@throws UnexpectedLiquibaseException with the message {@link #INVALID_STRING_ENCODING_MESSAGE} if an issue is found.

Catch any characters that will cause problems when parsing the XML down the road .


public Element createNode(String nodeNamespace, String nodeName, String nodeContent) {
        Element element = currentChangeLogFileDOM.createElementNS(nodeNamespace, nodeName);
        element.setTextContent(nodeContent);
        return element;
    }

public Element createNode ( String nodeNamespace , String nodeName , String nodeContent ) { Element element = currentChangeLogFileDOM . createElementNS ( nodeNamespace , nodeName ) ; element . setTextContent ( nodeContent ) ; return element ; }

create a XML node with nodeName and simple text content


public static void notNull(Object object, String failMessage) throws UnexpectedLiquibaseException {
        if (object == null) {
            fail(failMessage);
        }
    }

public static void notNull ( Object object , String failMessage ) throws UnexpectedLiquibaseException { if ( object == null ) { fail ( failMessage ) ; } }

Throws exception if passed object is null


boolean isSybaseProductName(String dbProductName) {
        return
                PRODUCT_NAME.equals(dbProductName)
                || "Sybase SQL Server".equals(dbProductName)
                || "sql server".equals(dbProductName)
                || "ASE".equals(dbProductName);
    }

boolean
isSybaseProductName
(
String
dbProductName
)
{
return
PRODUCT_NAME
.
equals
(
dbProductName
)
||
"Sybase SQL Server"
.
equals
(
dbProductName
)
||
"sql server"
.
equals
(
dbProductName
)
||
"ASE"
.
equals
(
dbProductName
)
;
}


public SqlVisitor create(String tagName) {
        Class<?> aClass = tagToClassMap.get(tagName);
        if (aClass == null) {
            return null;
        }
        try {
            return (SqlVisitor) aClass.getConstructor().newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

public SqlVisitor create ( String tagName ) { Class < ? > aClass = tagToClassMap . get ( tagName ) ; if ( aClass == null ) { return null ; } try { return ( SqlVisitor ) aClass . getConstructor ( ) . newInstance ( ) ; } catch ( Exception e ) { throw new RuntimeException ( e ) ; } }

Create a new Change subclass based on the given tag name.

Create a new Change subclass based on the given tag name .


public static String getLocalHostAddress() throws UnknownHostException, SocketException {
        try {
            return getLocalHost().getHostAddress();
        } catch (Exception e) {
            Scope.getCurrentScope().getLog(NetUtil.class).fine(LogType.LOG, "Error getting hostname", e);
            return "unknown";
        }
    }

public
static
String
getLocalHostAddress
(
)
throws
UnknownHostException
,
SocketException
{
try
{
return
getLocalHost
(
)
.
getHostAddress
(
)
;
}
catch
(
Exception
e
)
{
Scope
.
getCurrentScope
(
)
.
getLog
(
NetUtil
.
class
)
.
fine
(
LogType
.
LOG
,
"Error getting hostname"
,
e
)
;
return
"unknown"
;
}
}

Returns Local Host IP Address
@return local Host IP address
@throws UnknownHostException
@throws SocketException


public static String getLocalHostName() throws UnknownHostException, SocketException {
        try {
            return getLocalHost().getHostName();
        } catch (Exception e) {
            Scope.getCurrentScope().getLog(NetUtil.class).fine(LogType.LOG, "Error getting hostname", e);
            return "unknown";
        }
    }

public
static
String
getLocalHostName
(
)
throws
UnknownHostException
,
SocketException
{
try
{
return
getLocalHost
(
)
.
getHostName
(
)
;
}
catch
(
Exception
e
)
{
Scope
.
getCurrentScope
(
)
.
getLog
(
NetUtil
.
class
)
.
fine
(
LogType
.
LOG
,
"Error getting hostname"
,
e
)
;
return
"unknown"
;
}
}

Returns Local Host Name
@return local Host Name
@throws UnknownHostException
@throws SocketException


public static void surroundWithSchemaSets(List<Sql> sql, String schemaName, Database database) {
        if ((StringUtil.trimToNull(schemaName) != null) && !LiquibaseConfiguration.getInstance().getProperty(ChangeLogParserCofiguration.class, ChangeLogParserCofiguration.USE_PROCEDURE_SCHEMA).getValue(Boolean.class)) {
            String defaultSchema = database.getDefaultSchemaName();
            if (database instanceof OracleDatabase) {
                sql.add(0, new UnparsedSql("ALTER SESSION SET CURRENT_SCHEMA=" + database.escapeObjectName(schemaName, Schema.class)));
                sql.add(new UnparsedSql("ALTER SESSION SET CURRENT_SCHEMA=" + database.escapeObjectName(defaultSchema, Schema.class)));
            } else if (database instanceof AbstractDb2Database) {
                sql.add(0, new UnparsedSql("SET CURRENT SCHEMA " + schemaName));
                sql.add(new UnparsedSql("SET CURRENT SCHEMA " + defaultSchema));
            }
        }
    }

public
static
void
surroundWithSchemaSets
(
List
<
Sql
>
sql
,
String
schemaName
,
Database
database
)
{
if
(
(
StringUtil
.
trimToNull
(
schemaName
)
!=
)
&&
!
LiquibaseConfiguration
.
getInstance
(
)
.
getProperty
(
ChangeLogParserCofiguration
.
class
,
ChangeLogParserCofiguration
.
USE_PROCEDURE_SCHEMA
)
.
getValue
(
Boolean
.
class
)
)
{
String
defaultSchema
=
database
.
getDefaultSchemaName
(
)
;
if
(
database
instanceof
OracleDatabase
)
{
sql
.
add
(
0
,
new
UnparsedSql
(
"ALTER SESSION SET CURRENT_SCHEMA="
+
database
.
escapeObjectName
(
schemaName
,
Schema
.
class
)
)
)
;
sql
.
add
(
new
UnparsedSql
(
"ALTER SESSION SET CURRENT_SCHEMA="
+
database
.
escapeObjectName
(
defaultSchema
,
Schema
.
class
)
)
)
;
}
else
if
(
database
instanceof
AbstractDb2Database
)
{
sql
.
add
(
0
,
new
UnparsedSql
(
"SET CURRENT SCHEMA "
+
schemaName
)
)
;
sql
.
add
(
new
UnparsedSql
(
"SET CURRENT SCHEMA "
+
defaultSchema
)
)
;
}
}
}

Convenience method for when the schemaName is set but we don't want to parse the body

Convenience method for when the schemaName is set but we don t want to parse the body


public static String addSchemaToText(String procedureText, String schemaName, String keywordBeforeName, Database database) {
        if (schemaName == null) {
            return procedureText;
        }
        if ((StringUtil.trimToNull(schemaName) != null) && LiquibaseConfiguration.getInstance().getProperty(ChangeLogParserCofiguration.class, ChangeLogParserCofiguration.USE_PROCEDURE_SCHEMA).getValue(Boolean.class)) {
            StringClauses parsedSql = SqlParser.parse(procedureText, true, true);
            StringClauses.ClauseIterator clauseIterator = parsedSql.getClauseIterator();
            Object next = "START";
            while ((next != null) && !next.toString().equalsIgnoreCase(keywordBeforeName) && clauseIterator.hasNext()) {
                if (!"PACKAGE".equalsIgnoreCase(keywordBeforeName) && "PACKAGE".equalsIgnoreCase((String) next)) {
                    return procedureText;
                }
                next = clauseIterator.nextNonWhitespace();
            }
            if ((next != null) && clauseIterator.hasNext()) {
                Object procNameClause = clauseIterator.nextNonWhitespace();
                if (procNameClause instanceof String) {
                    String[] nameParts = ((String) procNameClause).split("\\.");
                    String finalName;
                    if (nameParts.length == 1) {
                        finalName = database.escapeObjectName(schemaName, Schema.class) + "." + nameParts[0];
                    } else if (nameParts.length == 2) {
                        finalName = database.escapeObjectName(schemaName, Schema.class) + "." + nameParts[1];
                    } else if (nameParts.length == 3) {
                        finalName = nameParts[0] + "." + database.escapeObjectName(schemaName, Schema.class) + "." + nameParts[2];
                    } else {
                        finalName = (String) procNameClause; //just go with what was there
                    }
                    clauseIterator.replace(finalName);
                }
                procedureText = parsedSql.toString();
            }
        }
        return procedureText;
    }

public
static
String
addSchemaToText
(
String
procedureText
,
String
schemaName
,
String
keywordBeforeName
,
Database
database
)
{
if
(
schemaName
==
)
{
return
procedureText
;
}
if
(
(
StringUtil
.
trimToNull
(
schemaName
)
!=
)
&&
LiquibaseConfiguration
.
getInstance
(
)
.
getProperty
(
ChangeLogParserCofiguration
.
class
,
ChangeLogParserCofiguration
.
USE_PROCEDURE_SCHEMA
)
.
getValue
(
Boolean
.
class
)
)
{
StringClauses
parsedSql
=
SqlParser
.
parse
(
procedureText
,
true
,
true
)
;
StringClauses
.
ClauseIterator
clauseIterator
=
parsedSql
.
getClauseIterator
(
)
;
Object
next
=
"START"
;
while
(
(
next
!=
)
&&
!
next
.
toString
(
)
.
equalsIgnoreCase
(
keywordBeforeName
)
&&
clauseIterator
.
hasNext
(
)
)
{
if
(
!
"PACKAGE"
.
equalsIgnoreCase
(
keywordBeforeName
)
&&
"PACKAGE"
.
equalsIgnoreCase
(
(
String
)
next
)
)
{
return
procedureText
;
}
next
=
clauseIterator
.
nextNonWhitespace
(
)
;
}
if
(
(
next
!=
)
&&
clauseIterator
.
hasNext
(
)
)
{
Object
procNameClause
=
clauseIterator
.
nextNonWhitespace
(
)
;
if
(
procNameClause
instanceof
String
)
{
String
[
]
nameParts
=
(
(
String
)
procNameClause
)
.
split
(
"\\."
)
;
String
finalName
;
if
(
nameParts
.
length
==
1
)
{
finalName
=
database
.
escapeObjectName
(
schemaName
,
Schema
.
class
)
+
"."
+
nameParts
[
0
]
;
}
else
if
(
nameParts
.
length
==
2
)
{
finalName
=
database
.
escapeObjectName
(
schemaName
,
Schema
.
class
)
+
"."
+
nameParts
[
1
]
;
}
else
if
(
nameParts
.
length
==
3
)
{
finalName
=
nameParts
[
0
]
+
"."
+
database
.
escapeObjectName
(
schemaName
,
Schema
.
class
)
+
"."
+
nameParts
[
2
]
;
}
else
{
finalName
=
(
String
)
procNameClause
;
//just go with what was there
}
clauseIterator
.
replace
(
finalName
)
;
}
procedureText
=
parsedSql
.
toString
(
)
;
}
}
return
procedureText
;
}

Convenience method for other classes similar to this that want to be able to modify the procedure text to add the schema


private static char[] encodeHex(byte[] data) {

        int l = data.length;

        char[] out = new char[l << 1];

        // two characters form the hex value.
        for (int i = 0, j = 0; i < l; i++) {
            out[j++] = DIGITS_LOWER[(0xF0 & data[i]) >>> 4];
            out[j++] = DIGITS_LOWER[0x0F & data[i]];
        }

        return out;
    }

private
static
char
[
]
encodeHex
(
byte
[
]
data
)
{
int
l
=
data
.
length
;
char
[
]
out
=
new
char
[
l
<<
1
]
;
// two characters form the hex value.
for
(
int
i
=
0
,
j
=
0
;
i
<
l
;
i
++
)
{
out
[
j
++
]
=
DIGITS_LOWER
[
(
0xF0
&
data
[
i
]
)
>>>
4
]
;
out
[
j
++
]
=
DIGITS_LOWER
[
0x0F
&
data
[
i
]
]
;
}
return
out
;
}

Converts an array of bytes into an array of characters representing the hexadecimal values of each byte in order.
The returned array will be double the length of the passed array, as it takes two characters to represent any
given byte.

@param data
a byte[] to convert to Hex characters
@return A char[] containing hexadecimal characters

Converts an array of bytes into an array of characters representing the hexadecimal values of each byte in order . The returned array will be double the length of the passed array as it takes two characters to represent any given byte .


protected String[] getDatabaseSchemaNames(Database database) throws SQLException, DatabaseException {
        List<String> returnList = new ArrayList<>();

        ResultSet schemas = null;
        try {
            schemas = ((JdbcConnection) database.getConnection()).getMetaData().getSchemas();
            while (schemas.next()) {
                returnList.add(JdbcUtils.getValueForColumn(schemas, "TABLE_SCHEM", database));
            }
        } finally {
            if (schemas != null) {
                schemas.close();
            }
        }

        return returnList.toArray(new String[returnList.size()]);
    }

protected String [ ] getDatabaseSchemaNames ( Database database ) throws SQLException , DatabaseException { List < String > returnList = new ArrayList <> ( ) ; ResultSet schemas = null ; try { schemas = ( ( JdbcConnection ) database . getConnection ( ) ) . getMetaData ( ) . getSchemas ( ) ; while ( schemas . next ( ) ) { returnList . add ( JdbcUtils . getValueForColumn ( schemas , "TABLE_SCHEM" , database ) ) ; } } finally { if ( schemas != null ) { schemas . close ( ) ; } } return returnList . toArray ( new String [ returnList . size ( ) ] ) ; }

Fetches an array of Strings with the schema names in the database.
@param database The database from which to get the schema names
@return An array of schema name Strings (May be an empty array)
@throws SQLException propagated java.sql.SQLException
@throws DatabaseException if a different problem occurs during the DBMS-specific code

Fetches an array of Strings with the schema names in the database .


public String[] readNext() throws IOException {

        String[] result = null;
        do {
            String nextLine = getNextLine();
            if (!hasNext) {
                return validateResult(result);
            }
            String[] r = parser.parseLineMulti(nextLine);
            if (r.length > 0) {
                if (result == null) {
                    result = r;
                } else {
                    result = combineResultsFromMultipleReads(result, r);
                }
            }
        } while (parser.isPending());
        return validateResult(result);
    }

public String [ ] readNext ( ) throws IOException { String [ ] result = null ; do { String nextLine = getNextLine ( ) ; if ( ! hasNext ) { return validateResult ( result ) ; } String [ ] r = parser . parseLineMulti ( nextLine ) ; if ( r . length > 0 ) { if ( result == null ) { result = r ; } else { result = combineResultsFromMultipleReads ( result , r ) ; } } } while ( parser . isPending ( ) ) ; return validateResult ( result ) ; }

Reads the next line from the buffer and converts to a string array.

@return a string array with each comma-separated element as a separate
entry.
@throws IOException if bad things happen during the read

Reads the next line from the buffer and converts to a string array .


protected String getNextLine() throws IOException {
        if (isClosed()) {
            hasNext = false;
            return null;
        }

        if (!this.linesSkiped) {
            for (int i = 0; i < skipLines; i++) {
                lineReader.readLine();
                linesRead++;
            }
            this.linesSkiped = true;
        }
        String nextLine = lineReader.readLine();
        if (nextLine == null) {
            hasNext = false;
        } else {
            linesRead++;
        }

        return hasNext ? nextLine : null;
    }

protected String getNextLine ( ) throws IOException { if ( isClosed ( ) ) { hasNext = false ; return null ; } if ( ! this . linesSkiped ) { for ( int i = 0 ; i < skipLines ; i ++ ) { lineReader . readLine ( ) ; linesRead ++ ; } this . linesSkiped = true ; } String nextLine = lineReader . readLine ( ) ; if ( nextLine == null ) { hasNext = false ; } else { linesRead ++ ; } return hasNext ? nextLine : null ; }

Reads the next line from the file.

@return the next line from the file without trailing newline
@throws IOException if bad things happen during the read


private boolean isClosed() {
        if (!verifyReader) {
            return false;
        }
        try {
            br.mark(READ_AHEAD_LIMIT);
            int nextByte = br.read();
            br.reset(); // resets stream position, possible because its buffered
            return nextByte == -1; // read() returns -1 at end of stream
        } catch (IOException e) {
            return true;
        }
    }

Checks to see if the file is closed.
@return true if the reader can no longer be read from.


public synchronized void startPolling(PolledConfigurationSource source, AbstractPollingScheduler scheduler) {
        this.scheduler = scheduler;
        this.source = source;
        init(source, scheduler);
        scheduler.startPolling(source, this);
    }

public synchronized void startPolling ( PolledConfigurationSource source , AbstractPollingScheduler scheduler ) { this . scheduler = scheduler ; this . source = source ; init ( source , scheduler ) ; scheduler . startPolling ( source , this ) ; }

Start polling the configuration source with the specified scheduler.

@param source PolledConfigurationSource to poll
@param scheduler AbstractPollingScheduler whose {@link AbstractPollingScheduler#schedule(Runnable)} will be
used to determine the polling schedule

Start polling the configuration source with the specified scheduler .


public void start() throws Exception {
    	// create the watcher for future configuration updatess
        pathChildrenCache.getListenable().addListener(new PathChildrenCacheListener() {
            public void childEvent(CuratorFramework aClient, PathChildrenCacheEvent event)
                    throws Exception {
                Type eventType = event.getType();
                ChildData data = event.getData();

                String path = null;
                if (data != null) {
                    path = data.getPath();

                    // scrub configRootPath out of the key name
                    String key = removeRootPath(path);

                    byte[] value = data.getData();
                    String stringValue = new String(value, charset);

                    logger.debug("received update to pathName [{}], eventType [{}]", path, eventType);
                    logger.debug("key [{}], and value [{}]", key, stringValue);

                    // fire event to all listeners
                    Map<String, Object> added = null;
                    Map<String, Object> changed = null;
                    Map<String, Object> deleted = null;
                    if (eventType == Type.CHILD_ADDED) {
                        added = new HashMap<String, Object>(1);
                        added.put(key, stringValue);
                    } else if (eventType == Type.CHILD_UPDATED) {
                        changed = new HashMap<String, Object>(1);
                        changed.put(key, stringValue);
                    } else if (eventType == Type.CHILD_REMOVED) {
                        deleted = new HashMap<String, Object>(1);
                        deleted.put(key, stringValue);
                    }

                    WatchedUpdateResult result = WatchedUpdateResult.createIncremental(added,
                        changed, deleted);

                    fireEvent(result);
                }
            }
        });

        // passing true to trigger an initial rebuild upon starting.  (blocking call)
        pathChildrenCache.start(true);
    }

Adds a listener to the pathChildrenCache, initializes the cache, then starts the cache-management background thread

@throws Exception

Adds a listener to the pathChildrenCache initializes the cache then starts the cache - management background thread


public static void setAppConfFolder(File appConfFolderFromConfig, String baseConfigFileName) {
		WebApplicationProperties.appConfFolder = appConfFolderFromConfig;
		WebApplicationProperties.baseConfigFileName = baseConfigFileName;
	}

public static void setAppConfFolder ( File appConfFolderFromConfig , String baseConfigFileName ) { WebApplicationProperties . appConfFolder = appConfFolderFromConfig ; WebApplicationProperties . baseConfigFileName = baseConfigFileName ; }

The folder where the application's properties files are located.

@param appConfFolderFromConfig
the folder as a File object where the
application's properties files are located
@param baseConfigFileName
the "base" name of the properties file. For e.g. if you have
config.properties, config-test.properties, then the value to
pass in is "config"

The folder where the application s properties files are located .


public DynamicIntProperty getIntProperty(String propName, int defaultValue, final Runnable propertyChangeCallback) {
        checkAndWarn(propName);
        DynamicIntProperty property = new DynamicIntProperty(propName, defaultValue);
        addCallback(propertyChangeCallback, property);
        return property;
    }

public DynamicIntProperty getIntProperty ( String propName , int defaultValue , final Runnable propertyChangeCallback ) { checkAndWarn ( propName ) ; DynamicIntProperty property = new DynamicIntProperty ( propName , defaultValue ) ; addCallback ( propertyChangeCallback , property ) ; return property ; }

Create a new property whose value is an integer and subject to change on-the-fly.

@param propName               property name
@param defaultValue           default value if the property is not defined in underlying configuration
@param propertyChangeCallback a Runnable to be called when the property is changed

Create a new property whose value is an integer and subject to change on - the - fly .


public DynamicLongProperty getLongProperty(String propName, long defaultValue, final Runnable propertyChangeCallback) {
        checkAndWarn(propName);
        DynamicLongProperty property = new DynamicLongProperty(propName, defaultValue);
        addCallback(propertyChangeCallback, property);
        return property;
    }

public DynamicLongProperty getLongProperty ( String propName , long defaultValue , final Runnable propertyChangeCallback ) { checkAndWarn ( propName ) ; DynamicLongProperty property = new DynamicLongProperty ( propName , defaultValue ) ; addCallback ( propertyChangeCallback , property ) ; return property ; }

Create a new property whose value is a long and subject to change on-the-fly.

@param propName               property name
@param defaultValue           default value if the property is not defined in underlying configuration
@param propertyChangeCallback a Runnable to be called when the property is changed

Create a new property whose value is a long and subject to change on - the - fly .


public DynamicBooleanProperty getBooleanProperty(String propName, boolean defaultValue, final Runnable propertyChangeCallback) {
        checkAndWarn(propName);
        DynamicBooleanProperty property = new DynamicBooleanProperty(propName, defaultValue);
        addCallback(propertyChangeCallback, property);
        return property;
    }

public DynamicBooleanProperty getBooleanProperty ( String propName , boolean defaultValue , final Runnable propertyChangeCallback ) { checkAndWarn ( propName ) ; DynamicBooleanProperty property = new DynamicBooleanProperty ( propName , defaultValue ) ; addCallback ( propertyChangeCallback , property ) ; return property ; }

Create a new property whose value is a boolean and subject to change on-the-fly.

@param propName               property name
@param defaultValue           default value if the property is not defined in underlying configuration
@param propertyChangeCallback a Runnable to be called when the property is changed

Create a new property whose value is a boolean and subject to change on - the - fly .


public DynamicFloatProperty getFloatProperty(String propName, float defaultValue, final Runnable propertyChangeCallback) {
        checkAndWarn(propName);
        DynamicFloatProperty property = new DynamicFloatProperty(propName, defaultValue);
        addCallback(propertyChangeCallback, property);
        return property;
    }

public DynamicFloatProperty getFloatProperty ( String propName , float defaultValue , final Runnable propertyChangeCallback ) { checkAndWarn ( propName ) ; DynamicFloatProperty property = new DynamicFloatProperty ( propName , defaultValue ) ; addCallback ( propertyChangeCallback , property ) ; return property ; }

Create a new property whose value is a float and subject to change on-the-fly.

@param propName               property name
@param defaultValue           default value if the property is not defined in underlying configuration
@param propertyChangeCallback a Runnable to be called when the property is changed

Create a new property whose value is a float and subject to change on - the - fly .


public DynamicDoubleProperty getDoubleProperty(String propName, double defaultValue, final Runnable propertyChangeCallback) {
        checkAndWarn(propName);
        DynamicDoubleProperty property = new DynamicDoubleProperty(propName, defaultValue);
        addCallback(propertyChangeCallback, property);
        return property;
    }

public DynamicDoubleProperty getDoubleProperty ( String propName , double defaultValue , final Runnable propertyChangeCallback ) { checkAndWarn ( propName ) ; DynamicDoubleProperty property = new DynamicDoubleProperty ( propName , defaultValue ) ; addCallback ( propertyChangeCallback , property ) ; return property ; }

Create a new property whose value is a double and subject to change on-the-fly.

@param propName               property name
@param defaultValue           default value if the property is not defined in underlying configuration
@param propertyChangeCallback a Runnable to be called when the property is changed

Create a new property whose value is a double and subject to change on - the - fly .


@Override
    protected Map<String, PropertyWithDeploymentContext> loadPropertiesFromTable(String table) {
        Map<String, PropertyWithDeploymentContext> propertyMap = new HashMap<String, PropertyWithDeploymentContext>();
        Map<String, AttributeValue> lastKeysEvaluated = null;
        do {
            ScanRequest scanRequest = new ScanRequest()
                    .withTableName(table)
                    .withExclusiveStartKey(lastKeysEvaluated);
            ScanResult result = dbScanWithThroughputBackOff(scanRequest);
            for (Map<String, AttributeValue> item : result.getItems()) {
                String keyVal = item.get(keyAttributeName.get()).getS();

                //Need to deal with the fact that these attributes might not exist
                DeploymentContext.ContextKey contextKey = item.containsKey(contextKeyAttributeName.get()) ? DeploymentContext.ContextKey.valueOf(item.get(contextKeyAttributeName.get()).getS()) : null;
                String contextVal = item.containsKey(contextValueAttributeName.get()) ? item.get(contextValueAttributeName.get()).getS() : null;
                String key = keyVal + ";" + contextKey + ";" + contextVal;
                propertyMap.put(key,
                        new PropertyWithDeploymentContext(
                                contextKey,
                                contextVal,
                                keyVal,
                                item.get(valueAttributeName.get()).getS()
                        ));
            }
            lastKeysEvaluated = result.getLastEvaluatedKey();
        } while (lastKeysEvaluated != null);
        return propertyMap;
    }

Scan the table in dynamo and create a map with the results.  In this case the map has a complex type as the value,
so that Deployment Context is taken into account.

@param table
@return

Scan the table in dynamo and create a map with the results . In this case the map has a complex type as the value so that Deployment Context is taken into account .


public static DynamicProperty getInstance(String propName) {
        // This is to ensure that a configuration source is registered with
        // DynamicProperty
        if (dynamicPropertySupportImpl == null) {
            DynamicPropertyFactory.getInstance();
        }
        DynamicProperty prop = ALL_PROPS.get(propName);
        if (prop == null) {
            prop = new DynamicProperty(propName);
            DynamicProperty oldProp = ALL_PROPS.putIfAbsent(propName, prop);
            if (oldProp != null) {
                prop = oldProp;
            }
        }
        return prop;
    }

Gets the DynamicProperty for a given property name.
This may be a previously constructed object,
or an object constructed on-demand to satisfy the request.

@param propName the name of the property
@return a DynamicProperty object that holds the cached value of
the configuration property named {@code propName}

Gets the DynamicProperty for a given property name . This may be a previously constructed object or an object constructed on - demand to satisfy the request .


private static boolean updateAllProperties() {
        boolean changed = false;
        for (DynamicProperty prop : ALL_PROPS.values()) {
            if (prop.updateValue()) {
                prop.notifyCallbacks();
                changed = true;
            }
        }
        return changed;
    }

private static boolean updateAllProperties ( ) { boolean changed = false ; for ( DynamicProperty prop : ALL_PROPS . values ( ) ) { if ( prop . updateValue ( ) ) { prop . notifyCallbacks ( ) ; changed = true ; } } return changed ; }

return true iff _some_ value actually changed


@Override
    public void addCallback(Runnable callback) {
        if (callback != null) {
            prop.addCallback(callback);
            callbacks.add(callback);
        }
    }

@ Override public void addCallback ( Runnable callback ) { if ( callback != null ) { prop . addCallback ( callback ) ; callbacks . add ( callback ) ; } }

Add the callback to be triggered when the value of the property is changed

@param callback


@Override
    public void removeAllCallbacks() {
        final Set<Runnable> callbacksToRemove = new HashSet<Runnable>(callbacks);
        for (Runnable callback : callbacksToRemove) {
            prop.removeCallback(callback);
        }
        callbacks.removeAll(callbacksToRemove);
    }

@ Override public void removeAllCallbacks ( ) { final Set < Runnable > callbacksToRemove = new HashSet < Runnable > ( callbacks ) ; for ( Runnable callback : callbacksToRemove ) { prop . removeCallback ( callback ) ; } callbacks . removeAll ( callbacksToRemove ) ; }

Remove all callbacks registered through this instance of property


public static HttpVerbUriRegexPropertyValue getVerbUriRegex(String propValue) {
        HttpVerbUriRegexPropertyValue returnValue = null;
        if (propValue != null) {
            propValue = propValue.trim();
            int methodSeparatorIndex = propValue.indexOf(METHOD_SEPARATOR);
            String uriRegex = propValue; // to begin with
            Verb verb = Verb.ANY_VERB;
            if (methodSeparatorIndex != -1) {
                // user may have supplied a verb
                verb = getVerb(propValue.substring(0, methodSeparatorIndex));
                if (verb != Verb.ANY_VERB) {
                    // update uriRegex
                    uriRegex = propValue.substring(methodSeparatorIndex + 1);
                }
            }
            returnValue = new HttpVerbUriRegexPropertyValue(verb, uriRegex);
        }
        return returnValue;
    }

public
static
HttpVerbUriRegexPropertyValue
getVerbUriRegex
(
String
propValue
)
{
HttpVerbUriRegexPropertyValue
returnValue
=
;
if
(
propValue
!=
)
{
propValue
=
propValue
.
trim
(
)
;
int
methodSeparatorIndex
=
propValue
.
indexOf
(
METHOD_SEPARATOR
)
;
String
uriRegex
=
propValue
;
// to begin with
Verb
verb
=
Verb
.
ANY_VERB
;
if
(
methodSeparatorIndex
!=
1
)
{
// user may have supplied a verb
verb
=
getVerb
(
propValue
.
substring
(
0
,
methodSeparatorIndex
)
)
;
if
(
verb
!=
Verb
.
ANY_VERB
)
{
// update uriRegex
uriRegex
=
propValue
.
substring
(
methodSeparatorIndex
+
1
)
;
}
}
returnValue
=
new
HttpVerbUriRegexPropertyValue
(
verb
,
uriRegex
)
;
}
return
returnValue
;
}

Expects property value to be of the form <uriRegex> OR <HTTP
Verb name><space><uriRegex>

@param propValue
property value
@return {@link HttpVerbUriRegexPropertyValue} instance corresponding to
propValue if propValue is not null, null otherwise

Expects property value to be of the form &lt ; uriRegex&gt ; OR &lt ; HTTP Verb name&gt ; &lt ; space&gt ; &lt ; uriRegex&gt ;


public static Properties loadPropertiesFromInputStream(InputStream fin) throws IOException {
        Properties props = new Properties();
        InputStreamReader reader = new InputStreamReader(fin, "UTF-8");
        try {
            props.load(reader);
            return props;
        } finally {
            if (reader != null) {
                reader.close();
            }
            if (fin != null) {
                fin.close();
            }
        }
    }

public static Properties loadPropertiesFromInputStream ( InputStream fin ) throws IOException { Properties props = new Properties ( ) ; InputStreamReader reader = new InputStreamReader ( fin , "UTF-8" ) ; try { props . load ( reader ) ; return props ; } finally { if ( reader != null ) { reader . close ( ) ; } if ( fin != null ) { fin . close ( ) ; } } }

Load properties from InputStream with utf-8 encoding, and it will take care of closing the input stream.
@param fin
@return
@throws IOException

Load properties from InputStream with utf - 8 encoding and it will take care of closing the input stream .


@Override
    public void addProperty(String name, Object value) {
        if (containsKey(name)) {
            // clear without triggering an event
            clearPropertyDirect(name);
        }
        super.addProperty(name, value);
    }

@
Override
public
void
addProperty
(
String
name
,
Object
value
)
{
if
(
containsKey
(
name
)
)
{
// clear without triggering an event
clearPropertyDirect
(
name
)
;
}
super
.
addProperty
(
name
,
value
)
;
}

Need to override this method for PDCLOUD-1809.

Need to override this method for PDCLOUD - 1809 .


public void updateProperties(final WatchedUpdateResult result, final Configuration config,
            final boolean ignoreDeletesFromSource) {
        if (result == null || !result.hasChanges()) {
            return;
        }

        logger.debug("incremental result? [{}]", result.isIncremental());
        logger.debug("ignored deletes from source? [{}]", ignoreDeletesFromSource);

        if (!result.isIncremental()) {
            Map<String, Object> props = result.getComplete();
            if (props == null) {
                return;
            }
            for (Entry<String, Object> entry : props.entrySet()) {
                addOrChangeProperty(entry.getKey(), entry.getValue(), config);
            }
            Set<String> existingKeys = new HashSet<String>();
            for (Iterator<String> i = config.getKeys(); i.hasNext();) {
                existingKeys.add(i.next());
            }
            if (!ignoreDeletesFromSource) {
                for (String key : existingKeys) {
                    if (!props.containsKey(key)) {
                        deleteProperty(key, config);
                    }
                }
            }
        } else {
            Map<String, Object> props = result.getAdded();
            if (props != null) {
                for (Entry<String, Object> entry : props.entrySet()) {
                    addOrChangeProperty(entry.getKey(), entry.getValue(), config);
                }
            }
            props = result.getChanged();
            if (props != null) {
                for (Entry<String, Object> entry : props.entrySet()) {
                    addOrChangeProperty(entry.getKey(), entry.getValue(), config);
                }
            }
            if (!ignoreDeletesFromSource) {
                props = result.getDeleted();
                if (props != null) {
                    for (String name : props.keySet()) {
                        deleteProperty(name, config);
                    }
                }
            }
        }
    }

public
void
updateProperties
(
final
WatchedUpdateResult
result
,
final
Configuration
config
,
final
boolean
ignoreDeletesFromSource
)
{
if
(
result
==
||
!
result
.
hasChanges
(
)
)
{
return
;
}
logger
.
debug
(
"incremental result? [{}]"
,
result
.
isIncremental
(
)
)
;
logger
.
debug
(
"ignored deletes from source? [{}]"
,
ignoreDeletesFromSource
)
;
if
(
!
result
.
isIncremental
(
)
)
{
Map
<
String
,
Object
>
props
=
result
.
getComplete
(
)
;
if
(
props
==
)
{
return
;
}
for
(
Entry
<
String
,
Object
>
entry
:
props
.
entrySet
(
)
)
{
addOrChangeProperty
(
entry
.
getKey
(
)
,
entry
.
getValue
(
)
,
config
)
;
}
Set
<
String
>
existingKeys
=
new
HashSet
<
String
>
(
)
;
for
(
Iterator
<
String
>
i
=
config
.
getKeys
(
)
;
i
.
hasNext
(
)
;
)
{
existingKeys
.
add
(
i
.
next
(
)
)
;
}
if
(
!
ignoreDeletesFromSource
)
{
for
(
String
key
:
existingKeys
)
{
if
(
!
props
.
containsKey
(
key
)
)
{
deleteProperty
(
key
,
config
)
;
}
}
}
}
else
{
Map
<
String
,
Object
>
props
=
result
.
getAdded
(
)
;
if
(
props
!=
)
{
for
(
Entry
<
String
,
Object
>
entry
:
props
.
entrySet
(
)
)
{
addOrChangeProperty
(
entry
.
getKey
(
)
,
entry
.
getValue
(
)
,
config
)
;
}
}
props
=
result
.
getChanged
(
)
;
if
(
props
!=
)
{
for
(
Entry
<
String
,
Object
>
entry
:
props
.
entrySet
(
)
)
{
addOrChangeProperty
(
entry
.
getKey
(
)
,
entry
.
getValue
(
)
,
config
)
;
}
}
if
(
!
ignoreDeletesFromSource
)
{
props
=
result
.
getDeleted
(
)
;
if
(
props
!=
)
{
for
(
String
name
:
props
.
keySet
(
)
)
{
deleteProperty
(
name
,
config
)
;
}
}
}
}
}

Updates the properties in the config param given the contents of the result param.

@param result
either an incremental or full set of data
@param config
underlying config map
@param ignoreDeletesFromSource
if true, deletes will be skipped

Updates the properties in the config param given the contents of the result param .


void addOrChangeProperty(final String name, final Object newValue, final Configuration config) {
        // We do not want to abort the operation due to failed validation on one property
        try {
            if (!config.containsKey(name)) {
                logger.debug("adding property key [{}], value [{}]", name, newValue);

                config.addProperty(name, newValue);
            } else {
                Object oldValue = config.getProperty(name);

                if (newValue != null) {
                    Object newValueArray;
                    if (oldValue instanceof CopyOnWriteArrayList && AbstractConfiguration.getDefaultListDelimiter() != '\0'){
                        newValueArray =
                                        new CopyOnWriteArrayList();

                      Iterable<String> stringiterator = Splitter.on(AbstractConfiguration.getDefaultListDelimiter()).omitEmptyStrings().trimResults().split((String)newValue);
                      for(String s :stringiterator){
                            ((CopyOnWriteArrayList) newValueArray).add(s);
                        }
                      } else {
                          newValueArray = newValue;
                      }

                    if (!newValueArray.equals(oldValue)) {
                        logger.debug("updating property key [{}], value [{}]", name, newValue);

                        config.setProperty(name, newValue);
                    }

                } else if (oldValue != null) {
                    logger.debug("nulling out property key [{}]", name);

                    config.setProperty(name, null);
                }
            }
        } catch (ValidationException e) {
            logger.warn("Validation failed for property " + name, e);
        }
    }

Add or update the property in the underlying config depending on if it exists

@param name
@param newValue
@param config


void deleteProperty(final String key, final Configuration config) {
        if (config.containsKey(key)) {
            logger.debug("deleting property key [" + key + "]");

            config.clearProperty(key);
        }
    }

void
deleteProperty
(
final
String
key
,
final
Configuration
config
)
{
if
(
config
.
containsKey
(
key
)
)
{
logger
.
debug
(
"deleting property key ["
+
key
+
"]"
)
;
config
.
clearProperty
(
key
)
;
}
}

Delete a property in the underlying config

@param key
@param config


@Override
    public void clear()
    {
        fireEvent(EVENT_CLEAR, null, null, true);
        map.clear();
        fireEvent(EVENT_CLEAR, null, null, false);
    }

@ Override public void clear ( ) { fireEvent ( EVENT_CLEAR , null , null , true ) ; map . clear ( ) ; fireEvent ( EVENT_CLEAR , null , null , false ) ; }

Clear the map and fire corresonding events.

Clear the map and fire corresonding events .


public Properties getProperties() {
        Properties p = new Properties();
        for (Iterator i = getKeys(); i.hasNext();) {
            String name = (String) i.next();
            String value = getString(name);
            p.put(name, value);
        }
        return p;
    }

public Properties getProperties ( ) { Properties p = new Properties ( ) ; for ( Iterator i = getKeys ( ) ; i . hasNext ( ) ; ) { String name = ( String ) i . next ( ) ; String value = getString ( name ) ; p . put ( name , value ) ; } return p ; }

Utility method to get a Properties object from this Configuration


protected synchronized void initialLoad(final PolledConfigurationSource source, final Configuration config) {
        PollResult result = null;
        try {
            result = source.poll(true, null);
            checkPoint = result.getCheckPoint();
            fireEvent(EventType.POLL_SUCCESS, result, null);
        } catch (Throwable e) {
            throw new RuntimeException("Unable to load Properties source from " + source, e);
        }
        try {
            populateProperties(result, config);
        } catch (Throwable e) {
            throw new RuntimeException("Unable to load Properties", e);
        }
    }

Do an initial poll from the source and apply the result to the configuration.

@param source source of the configuration
@param config Configuration to apply the polling result
@throws RuntimeException if any error occurs in polling the configuration source

Do an initial poll from the source and apply the result to the configuration .


public void addConfigurationAtIndex(AbstractConfiguration config, String name, int index)
    throws IndexOutOfBoundsException {
        if (!configList.contains(config)) {
            checkIndex(index);
            configList.add(index, config);
            if (name != null) {
                namedConfigurations.put(name, config);
            }
            config.addConfigurationListener(eventPropagater);
            fireEvent(EVENT_CONFIGURATION_SOURCE_CHANGED, null, null, false);
        } else {
            logger.warn(config + " is not added as it already exits");
        }
    }

public
void
addConfigurationAtIndex
(
AbstractConfiguration
config
,
String
name
,
int
index
)
throws
IndexOutOfBoundsException
{
if
(
!
configList
.
contains
(
config
)
)
{
checkIndex
(
index
)
;
configList
.
add
(
index
,
config
)
;
if
(
name
!=
)
{
namedConfigurations
.
put
(
name
,
config
)
;
}
config
.
addConfigurationListener
(
eventPropagater
)
;
fireEvent
(
EVENT_CONFIGURATION_SOURCE_CHANGED
,
,
,
false
)
;
}
else
{
logger
.
warn
(
config
+
" is not added as it already exits"
)
;
}
}

Add a configuration with a name at a particular index.

@throws IndexOutOfBoundsException

Add a configuration with a name at a particular index .


public  boolean removeConfiguration(Configuration config)
    {
        // Make sure that you can't remove the inMemoryConfiguration from
        // the CompositeConfiguration object
        if (!config.equals(containerConfiguration))
        {
            String configName = getNameForConfiguration(config);
            if (configName != null) {
                namedConfigurations.remove(configName);
            }
            return configList.remove(config);
        } else {
            throw new IllegalArgumentException("Can't remove container configuration");
        }
    }

Remove a configuration. The container configuration cannot be removed.

@param config The configuration to remove

Remove a configuration . The container configuration cannot be removed .


public Configuration removeConfiguration(String name)
    {
        Configuration conf = getConfiguration(name);
        if (conf != null && !conf.equals(containerConfiguration))
        {
            configList.remove(conf);
            namedConfigurations.remove(name);
        } else if (conf != null && conf.equals(containerConfiguration)) {
            throw new IllegalArgumentException("Can't remove container configuration");
        }
        return conf;
    }

public
Configuration
removeConfiguration
(
String
name
)
{
Configuration
conf
=
getConfiguration
(
name
)
;
if
(
conf
!=
&&
!
conf
.
equals
(
containerConfiguration
)
)
{
configList
.
remove
(
conf
)
;
namedConfigurations
.
remove
(
name
)
;
}
else
if
(
conf
!=
&&
conf
.
equals
(
containerConfiguration
)
)
{
throw
new
IllegalArgumentException
(
"Can't remove container configuration"
)
;
}
return
conf
;
}

Removes the configuration with the specified name.

@param name the name of the configuration to be removed
@return the removed configuration (<b>null</b> if this configuration
was not found)

Removes the configuration with the specified name .


public Iterator<String> getKeys() throws ConcurrentModificationException
    {
        Set<String> keys = new LinkedHashSet<String>();
        for (Iterator<String> it = overrideProperties.getKeys(); it.hasNext();) {
            keys.add(it.next());
        }
        for (Configuration config : configList)
        {
            for (Iterator<String> it = config.getKeys(); it.hasNext();)
            {
                try {
                    keys.add(it.next());
                } catch (ConcurrentModificationException e) {
                    logger.error("unexpected exception when iterating the keys for configuration " + config
                            + " with name " + getNameForConfiguration(config));
                    throw e;
                }
            }
        }

        return keys.iterator();
    }

Get all the keys contained by sub configurations.

@throws ConcurrentModificationException if concurrent modification happens on any sub configuration
when it is iterated to get all the keys

Get all the keys contained by sub configurations .


@Override
    public Iterator<String> getKeys(String prefix)
    {
        Set<String> keys = new LinkedHashSet<String>();
        for (Iterator<String> it = overrideProperties.getKeys(prefix); it.hasNext();) {
            keys.add(it.next());
        }
        for (Configuration config : configList)
        {
            for (Iterator<String> it = config.getKeys(prefix); it.hasNext();)
            {
                keys.add(it.next());
            }
        }

        return keys.iterator();
    }

@ Override public Iterator < String > getKeys ( String prefix ) { Set < String > keys = new LinkedHashSet < String > ( ) ; for ( Iterator < String > it = overrideProperties . getKeys ( prefix ) ; it . hasNext ( ) ; ) { keys . add ( it . next ( ) ) ; } for ( Configuration config : configList ) { for ( Iterator < String > it = config . getKeys ( prefix ) ; it . hasNext ( ) ; ) { keys . add ( it . next ( ) ) ; } } return keys . iterator ( ) ; }

Get the list of the keys contained in the sub configurations that match the
specified prefix.

Get the list of the keys contained in the sub configurations that match the specified prefix .


@Override
    public boolean containsKey(String key)
    {
        if (overrideProperties.containsKey(key)) {
            return true;
        }
        for (Configuration config : configList)
        {
            if (config.containsKey(key))
            {
                return true;
            }
        }
        return false;
    }

@ Override public boolean containsKey ( String key ) { if ( overrideProperties . containsKey ( key ) ) { return true ; } for ( Configuration config : configList ) { if ( config . containsKey ( key ) ) { return true ; } } return false ; }

Check if the any of the sub configurations contains the specified key.

@param key the key whose presence in this configuration is to be tested

@return true if the configuration contains a value for this
key, false otherwise

Check if the any of the sub configurations contains the specified key .


@Override
    public List getList(String key, List defaultValue)
    {
        List<Object> list = new ArrayList<Object>();

        // add all elements from the first configuration containing the requested key
        Iterator<AbstractConfiguration> it = configList.iterator();
        if (overrideProperties.containsKey(key)) {
            appendListProperty(list, overrideProperties, key);
        }
        while (it.hasNext() && list.isEmpty())
        {
            Configuration config = it.next();
            if ((config != containerConfiguration || containerConfigurationChanged)
                    && config.containsKey(key))
            {
                appendListProperty(list, config, key);
            }
        }

        // add all elements from the in memory configuration
        if (list.isEmpty()) {
            appendListProperty(list, containerConfiguration, key);
        }

        if (list.isEmpty())
        {
            return defaultValue;
        }

        ListIterator<Object> lit = list.listIterator();
        while (lit.hasNext())
        {
            lit.set(interpolate(lit.next()));
        }

        return list;
    }

Get a List of objects associated with the given configuration key.
If the key doesn't map to an existing object, the default value
is returned.

@param key The configuration key.
@param defaultValue The default value.
@return The associated List of value.

Get a List of objects associated with the given configuration key . If the key doesn t map to an existing object the default value is returned .


@Override
    public String[] getStringArray(String key)
    {
        List<Object> list = getList(key);

        // transform property values into strings
        String[] tokens = new String[list.size()];

        for (int i = 0; i < tokens.length; i++)
        {
            tokens[i] = String.valueOf(list.get(i));
        }

        return tokens;
    }

Get an array of strings associated with the given configuration key.
If the key doesn't map to an existing object an empty array is returned

@param key The configuration key.
@return The associated string array if key is found.

Get an array of strings associated with the given configuration key . If the key doesn t map to an existing object an empty array is returned


public static void loadCascadedPropertiesFromResources(String configName) throws IOException {
        Properties props = loadCascadedProperties(configName);
        if (instance instanceof AggregatedConfiguration) {
            ConcurrentMapConfiguration config = new ConcurrentMapConfiguration();
            config.loadProperties(props);
            ((AggregatedConfiguration) instance).addConfiguration(config, configName);
        } else {
            ConfigurationUtils.loadProperties(props, instance);
        }
    }

public static void loadCascadedPropertiesFromResources ( String configName ) throws IOException { Properties props = loadCascadedProperties ( configName ) ; if ( instance instanceof AggregatedConfiguration ) { ConcurrentMapConfiguration config = new ConcurrentMapConfiguration ( ) ; config . loadProperties ( props ) ; ( ( AggregatedConfiguration ) instance ) . addConfiguration ( config , configName ) ; } else { ConfigurationUtils . loadProperties ( props , instance ) ; } }

Load resource configName.properties first. Then load configName-deploymentEnvironment.properties
into the system wide configuration. For example, if configName is "application", and deployment environment
is "test", this API will first load "application.properties", then load "application-test.properties" to
override any property that also exist in "application.properties".

@param configName prefix of the properties file name.
@throws IOException
@see DeploymentContext#getDeploymentEnvironment()

Load resource configName . properties first . Then load configName - deploymentEnvironment . properties into the system wide configuration . For example if configName is application and deployment environment is test this API will first load application . properties then load application - test . properties to override any property that also exist in application . properties .


public static void loadPropertiesFromConfiguration(AbstractConfiguration config) {
        if (instance == null) {
            instance = getConfigInstance();
        }
        if (instance instanceof AggregatedConfiguration) {
            ((AggregatedConfiguration) instance).addConfiguration(config);
        } else {
            Properties props = ConfigurationUtils.getProperties(config);
            ConfigurationUtils.loadProperties(props, instance);
        }
    }

public static void loadPropertiesFromConfiguration ( AbstractConfiguration config ) { if ( instance == null ) { instance = getConfigInstance ( ) ; } if ( instance instanceof AggregatedConfiguration ) { ( ( AggregatedConfiguration ) instance ) . addConfiguration ( config ) ; } else { Properties props = ConfigurationUtils . getProperties ( config ) ; ConfigurationUtils . loadProperties ( props , instance ) ; } }

Load properties from the specified configuration into system wide configuration


public static void loadProperties(Properties properties) {
        if (instance == null) {
            instance = getConfigInstance();
        }
        ConfigurationUtils.loadProperties(properties, instance);
    }

public static void loadProperties ( Properties properties ) { if ( instance == null ) { instance = getConfigInstance ( ) ; } ConfigurationUtils . loadProperties ( properties , instance ) ; }

Load the specified properties into system wide configuration


@Override
    public PollResult poll(boolean initial, Object checkPoint)
            throws IOException {
        if (configUrls == null || configUrls.length == 0) {
            return PollResult.createFull(null);
        }
        Map<String, Object> map = new HashMap<String, Object>();
        for (URL url: configUrls) {
            InputStream fin = url.openStream();
            Properties props = ConfigurationUtils.loadPropertiesFromInputStream(fin);
            for (Entry<Object, Object> entry: props.entrySet()) {
                map.put((String) entry.getKey(), entry.getValue());
            }
        }
        return PollResult.createFull(map);
    }

@ Override public PollResult poll ( boolean initial , Object checkPoint ) throws IOException { if ( configUrls == null || configUrls . length == 0 ) { return PollResult . createFull ( null ) ; } Map < String , Object > map = new HashMap < String , Object > ( ) ; for ( URL url : configUrls ) { InputStream fin = url . openStream ( ) ; Properties props = ConfigurationUtils . loadPropertiesFromInputStream ( fin ) ; for ( Entry < Object , Object > entry : props . entrySet ( ) ) { map . put ( ( String ) entry . getKey ( ) , entry . getValue ( ) ) ; } } return PollResult . createFull ( map ) ; }

Retrieve the content of the property files. For each poll, it always
returns the complete union of properties defined in all URLs. If one
property is defined in content of more than one URL, the value in file later on the
list will override the value in the previous one.

@param initial this parameter is ignored by the implementation
@param checkPoint this parameter is ignored by the implementation
@throws IOException IOException occurred in file operation

Retrieve the content of the property files . For each poll it always returns the complete union of properties defined in all URLs . If one property is defined in content of more than one URL the value in file later on the list will override the value in the previous one .


public double getAngle(Location location) {
        // Euclidean distance (Pythagorean theorem) - not correct when the surface is a sphere
        double latitudeDifference = location.latitude - latitude;
        double longitudeDifference = location.longitude - longitude;
        return Math.atan2(latitudeDifference, longitudeDifference);
    }

The angle relative to the direction EAST.
@param location never null
@return in Cartesian coordinates

The angle relative to the direction EAST .


@Override
    public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
        // This might look like a Double Checked Idiom (which is broken), but it is not
        // because value is not a global variable
        V value = get(key);
        if (value != null) {
            return value;
        }
        return super.computeIfAbsent(key, mappingFunction);
    }

An overridden implementation that heavily favors read access over write access speed.
This is thread-safe.

{@inheritDoc}

An overridden implementation that heavily favors read access over write access speed . This is thread - safe .


public static void main(String[] args) {
        CloudBalancingGenerator generator = new CloudBalancingGenerator();
        generator.writeCloudBalance(2, 6);
        generator.writeCloudBalance(3, 9);
        generator.writeCloudBalance(4, 12);
//        generator.writeCloudBalance(5, 15);
//        generator.writeCloudBalance(6, 18);
//        generator.writeCloudBalance(7, 21);
//        generator.writeCloudBalance(8, 24);
//        generator.writeCloudBalance(9, 27);
//        generator.writeCloudBalance(10, 30);
//        generator.writeCloudBalance(11, 33);
//        generator.writeCloudBalance(12, 36);
//        generator.writeCloudBalance(13, 39);
//        generator.writeCloudBalance(14, 42);
//        generator.writeCloudBalance(15, 45);
//        generator.writeCloudBalance(16, 48);
//        generator.writeCloudBalance(17, 51);
//        generator.writeCloudBalance(18, 54);
//        generator.writeCloudBalance(19, 57);
//        generator.writeCloudBalance(20, 60);
        generator.writeCloudBalance(100, 300);
        generator.writeCloudBalance(200, 600);
        generator.writeCloudBalance(400, 1200);
        generator.writeCloudBalance(800, 2400);
        generator.writeCloudBalance(1600, 4800);
    }

//        generator.writeCloudBalance(5, 15);

//        generator.writeCloudBalance(6, 18);

//        generator.writeCloudBalance(7, 21);

//        generator.writeCloudBalance(8, 24);

//        generator.writeCloudBalance(9, 27);

//        generator.writeCloudBalance(10, 30);

//        generator.writeCloudBalance(11, 33);

//        generator.writeCloudBalance(12, 36);

//        generator.writeCloudBalance(13, 39);

//        generator.writeCloudBalance(14, 42);

//        generator.writeCloudBalance(15, 45);

//        generator.writeCloudBalance(16, 48);

//        generator.writeCloudBalance(17, 51);

//        generator.writeCloudBalance(18, 54);

//        generator.writeCloudBalance(19, 57);

//        generator.writeCloudBalance(20, 60);


public static String getGetterPropertyName(Member member) {
        if (member instanceof Field) {
            return member.getName();
        } else if (member instanceof Method) {
            String methodName = member.getName();
            for (String prefix : PROPERTY_ACCESSOR_PREFIXES) {
                if (methodName.startsWith(prefix)) {
                    return decapitalizePropertyName(methodName.substring(prefix.length()));
                }
            }
        }
        return null;
    }

public static String getGetterPropertyName ( Member member ) { if ( member instanceof Field ) { return member . getName ( ) ; } else if ( member instanceof Method ) { String methodName = member . getName ( ) ; for ( String prefix : PROPERTY_ACCESSOR_PREFIXES ) { if ( methodName . startsWith ( prefix ) ) { return decapitalizePropertyName ( methodName . substring ( prefix . length ( ) ) ) ; } } } return null ; }

Returns the JavaBeans property name of the given member.
@param member never null
@return null if the member is neither a field nor a getter method according to the JavaBeans standard

Returns the JavaBeans property name of the given member .


public static boolean isGetterMethod(Method method) {
        if (method.getParameterTypes().length != 0) {
            return false;
        }
        String methodName = method.getName();
        if (methodName.startsWith(PROPERTY_ACCESSOR_PREFIX_GET) && method.getReturnType() != void.class) {
            return true;
        } else if (methodName.startsWith(PROPERTY_ACCESSOR_PREFIX_IS) && method.getReturnType() == boolean.class) {
            return true;
        }
        return false;
    }

public static boolean isGetterMethod ( Method method ) { if ( method . getParameterTypes ( ) . length != 0 ) { return false ; } String methodName = method . getName ( ) ; if ( methodName . startsWith ( PROPERTY_ACCESSOR_PREFIX_GET ) && method . getReturnType ( ) != void . class ) { return true ; } else if ( methodName . startsWith ( PROPERTY_ACCESSOR_PREFIX_IS ) && method . getReturnType ( ) == boolean . class ) { return true ; } return false ; }

Checks whether the given method is a valid getter method according to the JavaBeans standard.
@param method never null
@return true if the given method is a getter method

Checks whether the given method is a valid getter method according to the JavaBeans standard .


public void addHardConstraintMatch(RuleContext kcontext, BigDecimal hardWeight) {
        hardScore = hardScore.add(hardWeight);
        registerConstraintMatch(kcontext,
                () -> hardScore = hardScore.subtract(hardWeight),
                () -> HardMediumSoftBigDecimalScore.of(hardWeight, BigDecimal.ZERO, BigDecimal.ZERO));
    }

public void addHardConstraintMatch ( RuleContext kcontext , BigDecimal hardWeight ) { hardScore = hardScore . add ( hardWeight ) ; registerConstraintMatch ( kcontext , ( ) -> hardScore = hardScore . subtract ( hardWeight ) , ( ) -> HardMediumSoftBigDecimalScore . of ( hardWeight , BigDecimal . ZERO , BigDecimal . ZERO ) ) ; }

Add a hard constraint of specified weighting.

This is typically used in Drools scoring to add a hard constraint match (negative value to indicate an infeasible
solution).

@param kcontext never null, the magic variable in DRL
@param hardWeight never null, higher is better, negative for a penalty, positive for a reward

Add a hard constraint of specified weighting .


public void addMediumConstraintMatch(RuleContext kcontext, BigDecimal mediumWeight) {
        mediumScore = mediumScore.add(mediumWeight);
        registerConstraintMatch(kcontext,
                () -> mediumScore = mediumScore.subtract(mediumWeight),
                () -> HardMediumSoftBigDecimalScore.of(BigDecimal.ZERO, mediumWeight, BigDecimal.ZERO));
    }

public void addMediumConstraintMatch ( RuleContext kcontext , BigDecimal mediumWeight ) { mediumScore = mediumScore . add ( mediumWeight ) ; registerConstraintMatch ( kcontext , ( ) -> mediumScore = mediumScore . subtract ( mediumWeight ) , ( ) -> HardMediumSoftBigDecimalScore . of ( BigDecimal . ZERO , mediumWeight , BigDecimal . ZERO ) ) ; }

Add a medium level constraint of specified weighting.

This is typically used in Drools scoring to add a medium priority constraint match.

@param kcontext never null, the magic variable in DRL
@param mediumWeight never null, higher is better, negative for a penalty, positive for a reward

Add a medium level constraint of specified weighting .


public void addSoftConstraintMatch(RuleContext kcontext, BigDecimal softWeight) {
        softScore = softScore.add(softWeight);
        registerConstraintMatch(kcontext,
                () -> softScore = softScore.subtract(softWeight),
                () -> HardMediumSoftBigDecimalScore.of(BigDecimal.ZERO, BigDecimal.ZERO, softWeight));
    }

public void addSoftConstraintMatch ( RuleContext kcontext , BigDecimal softWeight ) { softScore = softScore . add ( softWeight ) ; registerConstraintMatch ( kcontext , ( ) -> softScore = softScore . subtract ( softWeight ) , ( ) -> HardMediumSoftBigDecimalScore . of ( BigDecimal . ZERO , BigDecimal . ZERO , softWeight ) ) ; }

Add a soft constraint match of specified weighting.

This is typically used in Drools scoring to add a low priority constraint match.

@param kcontext never null, the magic variable in DRL
@param softWeight never null, higher is better, negative for a penalty, positive for a reward

Add a soft constraint match of specified weighting .


public static String cleanPath(final URL url) {
        String path = url.getPath();
        try {
            path = URLDecoder.decode(path, "UTF-8");
        } catch (UnsupportedEncodingException e) { /**/ }
        if (path.startsWith("jar:")) {
            path = path.substring("jar:".length());
        }
        if (path.startsWith("file:")) {
            path = path.substring("file:".length());
        }
        if (path.endsWith("!/")) {
            path = path.substring(0, path.lastIndexOf("!/")) + "/";
        }
        return path;
    }

public static String cleanPath ( final URL url ) { String path = url . getPath ( ) ; try { path = URLDecoder . decode ( path , "UTF-8" ) ; } catch ( UnsupportedEncodingException e ) { /**/ } if ( path . startsWith ( "jar:" ) ) { path = path . substring ( "jar:" . length ( ) ) ; } if ( path . startsWith ( "file:" ) ) { path = path . substring ( "file:" . length ( ) ) ; } if ( path . endsWith ( "!/" ) ) { path = path . substring ( 0 , path . lastIndexOf ( "!/" ) ) + "/" ; } return path ; }

Cleans the URL.

@param url  the URL to clean, not null
@return the path, not null


public long calculateStandardDeviationSquaredFemtos() {
        long totalFemtos = 0L;
        for (AssetClassAllocation a : assetClassAllocationList) {
            for (AssetClassAllocation b : assetClassAllocationList) {
                if (a == b) {
                    totalFemtos += a.getQuantifiedStandardDeviationRiskMicros() * b.getQuantifiedStandardDeviationRiskMicros()
                            * 1000L;
                } else {
                    // Matches twice: once for (A, B) and once for (B, A)
                    long correlationMillis = a.getAssetClass().getCorrelationMillisMap().get(b.getAssetClass());
                    totalFemtos += a.getQuantifiedStandardDeviationRiskMicros() * b.getQuantifiedStandardDeviationRiskMicros()
                            * correlationMillis;
                }
            }
        }
        return totalFemtos;
    }


public void checkIfProblemFactsExist() {
        if (problemFactCollectionMemberAccessorMap.isEmpty() && problemFactMemberAccessorMap.isEmpty()) {
            throw new IllegalStateException("The solutionClass (" + solutionClass
                    + ") must have at least 1 member with a "
                    + ProblemFactCollectionProperty.class.getSimpleName() + " annotation or a "
                    + ProblemFactProperty.class.getSimpleName() + " annotation"
                    + " when used with Drools score calculation.");
        }
    }

Only called if Drools score calculation is used.

Only called if Drools score calculation is used .


public long getProblemScale(Solution_ solution) {
        long problemScale = 0L;
        for (Iterator<Object> it = extractAllEntitiesIterator(solution); it.hasNext(); ) {
            Object entity = it.next();
            EntityDescriptor<Solution_> entityDescriptor = findEntityDescriptorOrFail(entity.getClass());
            problemScale += entityDescriptor.getProblemScale(solution, entity);
        }
        return problemScale;
    }

public long getProblemScale ( Solution_ solution ) { long problemScale = 0L ; for ( Iterator < Object > it = extractAllEntitiesIterator ( solution ) ; it . hasNext ( ) ; ) { Object entity = it . next ( ) ; EntityDescriptor < Solution_ > entityDescriptor = findEntityDescriptorOrFail ( entity . getClass ( ) ) ; problemScale += entityDescriptor . getProblemScale ( solution , entity ) ; } return problemScale ; }

Calculates an indication on how big this problem instance is.
This is intentionally very loosely defined for now.
@param solution never null
@return {@code >= 0}

Calculates an indication on how big this problem instance is . This is intentionally very loosely defined for now .


static String generateTaskName(final Request<?> request) {
    return request.getBaseUriTemplate() + " "
        + OperationNameGenerator.generate(request.getMethod(), request.getMethodName());
  }

static
String
generateTaskName
(
final
Request
<
>
request
)
{
return
request
.
getBaseUriTemplate
(
)
+
" "
+
OperationNameGenerator
.
generate
(
request
.
getMethod
(
)
,
request
.
getMethodName
(
)
)
;
}

Generates a task name for the request.
@param request
@return a task name


private boolean hasRequestContextTimeout(RequestContext requestContext) {
    Object requestTimeout = requestContext.getLocalAttr(R2Constants.REQUEST_TIMEOUT);
    return (requestTimeout instanceof Number) && (((Number)requestTimeout).intValue() > 0);
  }

private boolean hasRequestContextTimeout ( RequestContext requestContext ) { Object requestTimeout = requestContext . getLocalAttr ( R2Constants . REQUEST_TIMEOUT ) ; return ( requestTimeout instanceof Number ) && ( ( ( Number ) requestTimeout ) . intValue ( ) > 0 ) ; }

Check whether per-request timeout is specified in the given request context.

Check whether per - request timeout is specified in the given request context .


private boolean needApplyTaskTimeout(RequestContext requestContext, ConfigValue<Long> timeout) {
    // return false if no timeout configured or per-request timeout already specified in request context
    return timeout.getValue() != null && timeout.getValue() > 0 && !hasRequestContextTimeout(requestContext);
  }

check whether we need to apply timeout to a rest.li request task.

check whether we need to apply timeout to a rest . li request task .


private <T> Task<Response<T>> createTaskWithTimeout(final String name, final Request<T> request,
      final RequestContext requestContext, RequestConfig config) {
    ConfigValue<Long> timeout = config.getTimeoutMs();
    Task<Response<T>> requestTask;
    if (RequestGroup.isBatchable(request, config)) {
      requestTask = createBatchableTask(name, request, requestContext, config);
    } else {
      requestTask = Task.async(name, () -> sendRequest(request, requestContext));
    }
    if (!needApplyTaskTimeout(requestContext, timeout)) {
      return requestTask;
    } else {
      return withTimeout(requestTask, timeout);
    }
  }

private < T > Task < Response < T > > createTaskWithTimeout ( final String name , final Request < T > request , final RequestContext requestContext , RequestConfig config ) { ConfigValue < Long > timeout = config . getTimeoutMs ( ) ; Task < Response < T > > requestTask ; if ( RequestGroup . isBatchable ( request , config ) ) { requestTask = createBatchableTask ( name , request , requestContext , config ) ; } else { requestTask = Task . async ( name , ( ) -> sendRequest ( request , requestContext ) ) ; } if ( ! needApplyTaskTimeout ( requestContext , timeout ) ) { return requestTask ; } else { return withTimeout ( requestTask , timeout ) ; } }

Apply timeout to a ParSeq rest.li request task through parseq timer task.

Apply timeout to a ParSeq rest . li request task through parseq timer task .


public Task<HttpResponse> build(final String hash, final InputStream body)
      throws IOException {
    if (hash == null) {
      // Missing hash
      String content = "Missing hash.";
      LOG.info(content);
      return Task.value(new HttpResponse(HttpServletResponse.SC_BAD_REQUEST, content));
    } else {
      // Have cache
      if (_hashManager.contains(hash)) {
        LOG.info("hash found in cache: " + hash);
        return Task.value(new HttpResponse(HttpServletResponse.SC_OK, ""));
      } else {
        if (body == null) {
          // Missing body
          String content = "Missing body.";
          LOG.info(content);
          return Task.value(new HttpResponse(HttpServletResponse.SC_BAD_REQUEST, content));
        } else if (_dotLocation == null) {
          // Missing dot
          String content = "Missing dot.";
          LOG.info(content);
          return Task.value(new HttpResponse(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, content));
        } else {
          // Build task
          final Task<Exec.Result> buildTask = getBuildTask(hash, body);
          return buildTask.transform("result", result -> {
            Integer status = null;
            String content = null;
            if (result.isFailed()) {
              // Task fail
              status = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
              content = result.getError().toString();
            } else {
              // Task success
              switch (result.get().getStatus()) {
                // Success
                case 0:
                  _hashManager.add(hash);
                  status = HttpServletResponse.SC_OK;
                  content = "";
                  break;
                // Timeout
                case 137:
                  status = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
                  content = "graphviz process was killed because it did not finish within " + _timeoutMs + "ms";
                  break;
                // Unknown
                default:
                  status = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
                  content = writeGenericFailureInfo(result.get());
                  break;
              }
            }
            // Clean up cache
            _inFlightBuildTasks.remove(hash, buildTask);
            return Success.of(new HttpResponse(status, content));
          });
        }
      }
    }
  }

Return task that has general HTTP status and body information based on the build task's result.

Return task that has general HTTP status and body information based on the build task s result .


private Task<Exec.Result> getBuildTask(final String hash, final InputStream body) {
    Task<Exec.Result> existing = _inFlightBuildTasks.get(hash);
    if (existing != null) {
      LOG.info("using in flight shareable: " + hash);
      return existing.shareable();
    } else {
      Task<Exec.Result> newBuildTask = createNewBuildTask(hash, body);
      existing = _inFlightBuildTasks.putIfAbsent(hash, newBuildTask);
      if (existing != null) {
        LOG.info("using in flight shareable: " + hash);
        return existing.shareable();
      } else {
        return newBuildTask;
      }
    }
  }

private
Task
<
Exec
.
Result
>
getBuildTask
(
final
String
hash
,
final
InputStream
body
)
{
Task
<
Exec
.
Result
>
existing
=
_inFlightBuildTasks
.
get
(
hash
)
;
if
(
existing
!=
)
{
LOG
.
info
(
"using in flight shareable: "
+
hash
)
;
return
existing
.
shareable
(
)
;
}
else
{
Task
<
Exec
.
Result
>
newBuildTask
=
createNewBuildTask
(
hash
,
body
)
;
existing
=
_inFlightBuildTasks
.
putIfAbsent
(
hash
,
newBuildTask
)
;
if
(
existing
!=
)
{
LOG
.
info
(
"using in flight shareable: "
+
hash
)
;
return
existing
.
shareable
(
)
;
}
else
{
return
newBuildTask
;
}
}
}

Returns task that builds graph using graphviz. Returned task might be shared with other concurrent requests.

Returns task that builds graph using graphviz . Returned task might be shared with other concurrent requests .


private Task<Exec.Result> createNewBuildTask(final String hash, final InputStream body) {

    LOG.info("building: " + hash);

    final Task<Void> createDotFile = Task.action("createDotFile",
        () -> Files.copy(body, pathToCacheFile(hash, "dot"), StandardCopyOption.REPLACE_EXISTING));

    // Task that runs a graphviz command.
    // We give process TIMEOUT_MS time to finish, after that
    // it will be forcefully killed.
    final Task<Exec.Result> graphviz = _exec
        .command("graphviz", _timeoutMs, TimeUnit.MILLISECONDS, _dotLocation, "-T" + Constants.OUTPUT_TYPE,
            "-Grankdir=LR", "-Gnewrank=true", "-Gbgcolor=transparent", pathToCacheFile(hash, "dot").toString(), "-o",
            pathToCacheFile(hash, Constants.OUTPUT_TYPE).toString());

    // Since Exec utility allows only certain number of processes
    // to run in parallel and rest is enqueued, we also specify
    // timeout on a task level equal to 2 * graphviz timeout.
    final Task<Exec.Result> graphvizWithTimeout = graphviz.withTimeout(_timeoutMs * 2, TimeUnit.MILLISECONDS);

    return createDotFile.andThen(graphvizWithTimeout);
  }

Returns new task that builds graph using graphviz.

Returns new task that builds graph using graphviz .


private String writeGenericFailureInfo(final Exec.Result result)
      throws IOException {
    StringBuilder sb = new StringBuilder();
    sb.append("graphviz process returned: ").append(result.getStatus()).append("\n").append("stdout:\n");
    Files.lines(result.getStdout()).forEach(sb::append);
    sb.append("stderr:\n");
    Files.lines(result.getStderr()).forEach(sb::append);
    return sb.toString();
  }

private
String
writeGenericFailureInfo
(
final
Exec
.
Result
result
)
throws
IOException
{
StringBuilder
sb
=
new
StringBuilder
(
)
;
sb
.
append
(
"graphviz process returned: "
)
.
append
(
result
.
getStatus
(
)
)
.
append
(
"\n"
)
.
append
(
"stdout:\n"
)
;
Files
.
lines
(
result
.
getStdout
(
)
)
.
forEach
(
sb
::
append
)
;
sb
.
append
(
"stderr:\n"
)
;
Files
.
lines
(
result
.
getStderr
(
)
)
.
forEach
(
sb
::
append
)
;
return
sb
.
toString
(
)
;
}


public static Trace single(ShallowTrace shallowTrace) {
    return single(shallowTrace, TraceBuilder.UNKNOWN_PLAN_CLASS, TraceBuilder.UNKNOWN_PLAN_ID);
  }

public static Trace single ( ShallowTrace shallowTrace ) { return single ( shallowTrace , TraceBuilder . UNKNOWN_PLAN_CLASS , TraceBuilder . UNKNOWN_PLAN_ID ) ; }

Need to fix in the next major version release.

Need to fix in the next major version release .


public Task<T> batchable(final String desc, final K key) {
    Task<T> batchableTask = Task.async(desc, ctx -> {
      final BatchPromise<T> result = new BatchPromise<>();
      final Long planId = ctx.getPlanId();
      final GroupBatchBuilder builder = _batches.computeIfAbsent(planId, k -> new GroupBatchBuilder());
      final G group = classify(key);
      Batch<K, T> fullBatch = builder.add(group, key, ctx.getShallowTraceBuilder(), result);
      if (fullBatch != null) {
        try {
          ctx.run(taskForBatch(group, fullBatch, true));
        } catch (Throwable t) {
          //we don't care if some of promises have already been completed
          //all we care is that all remaining promises have been failed
          fullBatch.failAll(t);
        }
      }
      return result;
    });
    batchableTask.getShallowTraceBuilder().setTaskType("batched");
    return batchableTask;
  }

This method returns Task that returns value for a single key allowing this strategy to batch operations.
@param desc description of the task
@param key key
@return Task that returns value for a single key allowing this strategy to batch operations

This method returns Task that returns value for a single key allowing this strategy to batch operations .


public String getBatchName(G group, Batch<K, T> batch) {
    return "batch(keys: " + batch.keySize() + ", size: " + batch.batchSize() + ")";
  }

public
String
getBatchName
(
G
group
,
Batch
<
K
,
T
>
batch
)
{
return
"batch(keys: "
+
batch
.
keySize
(
)
+
", size: "
+
batch
.
batchSize
(
)
+
")"
;
}

Overriding this method allows providing custom name for a batch. Name will appear in the
ParSeq trace as a description of the task that executes the batch.
@param batch batch to be described
@param group group to be described
@return name for the batch and group

Overriding this method allows providing custom name for a batch . Name will appear in the ParSeq trace as a description of the task that executes the batch .


public synchronized <T> T harvest(Function<Histogram, T> consumer) {
    initializeRecorder();
    _recycle = _recorder.getIntervalHistogram(_recycle);
    return consumer.apply(_recycle);
  }

public synchronized < T > T harvest ( Function < Histogram , T > consumer ) { initializeRecorder ( ) ; _recycle = _recorder . getIntervalHistogram ( _recycle ) ; return consumer . apply ( _recycle ) ; }

Allows consuming histogram and returning a result.
Histogram passed to the consumer includes stable, consistent view
of all values accumulated since last harvest.
This method is thread safe.
@param consumer consumer for a harvested histogram
@param <T> return type of a passed in function
@return a result of a passed in function

Allows consuming histogram and returning a result . Histogram passed to the consumer includes stable consistent view of all values accumulated since last harvest . This method is thread safe .


private static ParSeqRestliClientConfig createDefaultConfig() {
    ParSeqRestliClientConfigBuilder builder = new ParSeqRestliClientConfigBuilder();
    builder.addTimeoutMs("*.*/*.*", DEFAULT_TIMEOUT);
    builder.addBatchingEnabled("*.*/*.*", DEFAULT_BATCHING_ENABLED);
    builder.addMaxBatchSize("*.*/*.*", DEFAULT_MAX_BATCH_SIZE);
    return builder.build();
  }

private static ParSeqRestliClientConfig createDefaultConfig ( ) { ParSeqRestliClientConfigBuilder builder = new ParSeqRestliClientConfigBuilder ( ) ; builder . addTimeoutMs ( "*.*/*.*" , DEFAULT_TIMEOUT ) ; builder . addBatchingEnabled ( "*.*/*.*" , DEFAULT_BATCHING_ENABLED ) ; builder . addMaxBatchSize ( "*.*/*.*" , DEFAULT_MAX_BATCH_SIZE ) ; return builder . build ( ) ; }

Default configuration map must specify default values for all properties.

Default configuration map must specify default values for all properties .


private <R> Consumer3<FusionTraceContext, Promise<S>, Settable<T>> compose(
      final Consumer3<FusionTraceContext, Promise<S>, Settable<R>> predecessor,
      final Consumer3<FusionTraceContext, Promise<R>, Settable<T>> propagator) {

    return (traceContext, src, dst) -> {

      /*
       * At this point we know that transformation chain's length > 1.
       * This code is executed during task execution, not when task is constructed.
       */
      traceContext.createSurrogate();

      predecessor.accept(traceContext, src, new Settable<R>() {

        @Override
        public void done(R value) throws PromiseResolvedException {
          try {
            /* Track start time of the transformation. End time is tracked by closure created by completing() */
            getEffectiveShallowTraceBuilder(traceContext).setStartNanos(System.nanoTime());
            propagator.accept(traceContext, Promises.value(value), dst);
          } catch (Exception e) {
            /* This can only happen if there is an internal problem. Propagators should not throw any exceptions. */
            LOGGER.error("ParSeq ingternal error. An exception was thrown by propagator", e);
          }
        }

        @Override
        public void fail(Throwable error) throws PromiseResolvedException {
          try {
            /* Track start time of the transformation. End time is tracked by closure created by completing() */
            getEffectiveShallowTraceBuilder(traceContext).setStartNanos(System.nanoTime());
            propagator.accept(traceContext, Promises.error(error), dst);
          } catch (Exception e) {
            /* This can only happen if there is an internal problem. Propagators should not throw any exceptions. */
            LOGGER.error("ParSeq ingternal error. An exception was thrown by propagator.", e);
          }
        }
      });
    };
  }

Composes transformation with the transformation of the predecessor.

Composes transformation with the transformation of the predecessor .


public static <S, T> FusionTask<?, T> create(final String name, final Task<S> task, final PromisePropagator<S, T> propagator) {
    return new FusionTask<S, T>(name, task, propagator);
  }

public static < S , T > FusionTask < ? , T > create ( final String name , final Task < S > task , final PromisePropagator < S , T > propagator ) { return new FusionTask < S , T > ( name , task , propagator ) ; }

Create new FusionTask with an async predecessor.

Create new FusionTask with an async predecessor .


public EngineBuilder setEngineProperty(String key, Object value) {
    _properties.put(key, value);
    return this;
  }

public EngineBuilder setEngineProperty ( String key , Object value ) { _properties . put ( key , value ) ; return this ; }

Sets an engine related property on the engine.
That property can then be accessed by tasks via the Context.

@param key
@param value
@return this builder

Sets an engine related property on the engine . That property can then be accessed by tasks via the Context .


@SuppressWarnings("unchecked")
  public static <T> Promise<T> value(final T value) {
    if (value == null) {
      if (VOID == null) {
        return new ResolvedValue<T>(value);
      } else {
        return (Promise<T>) VOID;
      }
    }
    return new ResolvedValue<T>(value);
  }

@ SuppressWarnings ( "unchecked" ) public static < T > Promise < T > value ( final T value ) { if ( value == null ) { if ( VOID == null ) { return new ResolvedValue < T > ( value ) ; } else { return ( Promise < T > ) VOID ; } } return new ResolvedValue < T > ( value ) ; }

Creates a new promise that is already resolved with the given value.

@param value the value for the new promise
@param <T> the type of the value for the promise
@return the promise

Creates a new promise that is already resolved with the given value .


public static <T> void propagateResult(final Promise<T> source, final Settable<T> dest) {
    source.addListener(new TransformingPromiseListener<T, T>(dest, PromiseTransformer.identity()));
  }

public static < T > void propagateResult ( final Promise < T > source , final Settable < T > dest ) { source . addListener ( new TransformingPromiseListener < T , T > ( dest , PromiseTransformer . identity ( ) ) ) ; }

Copies the value or error from the source promise to the destination
promise.

@param source the source promise
@param dest the destination promise
@param <T> the value type for both promises

Copies the value or error from the source promise to the destination promise .


Task<String> createResilientSummary(int id) {
    return fetchPerson(id).map(this::shortSummary).recover(e -> "Member " + id);
  }

Task
<
String
>
createResilientSummary
(
int
id
)
{
return
fetchPerson
(
id
)
.
map
(
this
::
shortSummary
)
.
recover
(
e
->
"Member "
+
id
)
;
}

handles failures delivering degraded experience


Task<String> createResponsiveSummary(int id) {
    return fetchPerson(id).withTimeout(100, TimeUnit.MILLISECONDS).map(this::shortSummary).recover(e -> "Member " + id);
  }

Task
<
String
>
createResponsiveSummary
(
int
id
)
{
return
fetchPerson
(
id
)
.
withTimeout
(
100
,
TimeUnit
.
MILLISECONDS
)
.
map
(
this
::
shortSummary
)
.
recover
(
e
->
"Member "
+
id
)
;
}

handles failures delivering degraded experience in timely fashion


Task<List<String>> createConnectionsSummaries(int id) {
    return fetchPerson(id).flatMap("createConnectionsSummaries", person -> createConnectionsSummaries(person.getConnections()));
  }

Task < List < String > > createConnectionsSummaries ( int id ) { return fetchPerson ( id ) . flatMap ( "createConnectionsSummaries" , person -> createConnectionsSummaries ( person . getConnections ( ) ) ) ; }

create list of summaries, one per each connection

create list of summaries one per each connection


@Deprecated
  public static <T> Task<T> withSideEffect(final Task<T> parent, final Task<?> sideEffect) {
    return parent.withSideEffect(t -> sideEffect);
  }

@ Deprecated public static < T > Task < T > withSideEffect ( final Task < T > parent , final Task < ? > sideEffect ) { return parent . withSideEffect ( t -> sideEffect ) ; }

Creates a task that will run another task as a side effect once the primary task
completes successfully. The side effect will not be run if the primary task fails or
is canceled. The entire task is marked done once the base task completes, even if
the side effect has not been run.

@param parent the primary task.
@param sideEffect the side effect of the primary task.
@param <T> the result value of the parent task, and the resulting task.
@return a new task that will be done once parent completes, but has the given side effect.
@deprecated  As of 2.0.0, replaced by {@link Task#withSideEffect(String, com.linkedin.parseq.function.Function1) Task.withSideEffect}
@see Task#withSideEffect(String, com.linkedin.parseq.function.Function1) Task.withSideEffect

Creates a task that will run another task as a side effect once the primary task completes successfully . The side effect will not be run if the primary task fails or is canceled . The entire task is marked done once the base task completes even if the side effect has not been run .


@Deprecated
  public static <T> Task<T> timeoutWithError(final long time, final TimeUnit unit, final Task<T> task) {
    return task.withTimeout(time, unit);
  }

@ Deprecated public static < T > Task < T > timeoutWithError ( final long time , final TimeUnit unit , final Task < T > task ) { return task . withTimeout ( time , unit ) ; }

Creates a new task that wraps the given task. If the given task finishes
before the timeout occurs then this task takes on the value of the task.
If the task does not complete in the given time then this task will
have a TimeoutException. The wrapped task may be cancelled when a timeout
occurs.

@param time the time to wait before timing out
@param unit the units for the time
@param task the task to wrap
@param <T> the value type for the task
@return the new timeout task
@deprecated  As of 2.0.0, replaced by {@link Task#withTimeout(long, TimeUnit) Task.withTimeout}.
@see Task#withTimeout(long, TimeUnit) Task.withTimeout

Creates a new task that wraps the given task . If the given task finishes before the timeout occurs then this task takes on the value of the task . If the task does not complete in the given time then this task will have a TimeoutException . The wrapped task may be cancelled when a timeout occurs .


public static String findNodeWithNextLowestSN(List<String> children, String node) {
    List<String> sortedChildren = children.stream()
        .sorted((String o1, String o2) ->
            Long.compare(getSequenceNumber(o1), getSequenceNumber(o2)))
        .collect(Collectors.toList());

    int index = sortedChildren.indexOf(node);
    if (index > 0) {
      return sortedChildren.get(index-1);
    } else if (index == 0) {
      return node;
    } else {
      return null;
    }
  }

public static String findNodeWithNextLowestSN ( List < String > children , String node ) { List < String > sortedChildren = children . stream ( ) . sorted ( ( String o1 , String o2 ) -> Long . compare ( getSequenceNumber ( o1 ) , getSequenceNumber ( o2 ) ) ) . collect ( Collectors . toList ( ) ) ; int index = sortedChildren . indexOf ( node ) ; if ( index > 0 ) { return sortedChildren . get ( index - 1 ) ; } else if ( index == 0 ) { return node ; } else { return null ; } }

Finds node with next lowest sequence number than the given node within
the given list of nodes.

@param children list of children
@param node the given node to compare sequence number with
@return the node with next lowest sequence number

Finds node with next lowest sequence number than the given node within the given list of nodes .