StringSubstitutor not working with JSON text - java

I am trying to do some String Substitution using the StringSubstitutor . My payload is often JSOn and it doesnt replaces the token always.
Example
String ss = "{\"media\":[{\"channels2\":\"[Token2]\",\"channels\":\"[Token1]\"}]}";
final Map<String, Object> tokenReplacementValues = new HashMap<>();
tokenReplacementValues.put("Token2", "33");
tokenReplacementValues.put("Token1", "22");
System.out.println("Tokens to tokenReplacementInstruction = {}" + tokenReplacementValues);
StringSubstitutor sub = new StringSubstitutor(tokenReplacementValues, "[", "]");
ss = sub.replace(ss);
System.out.println("After Token Replacement: " + ss);
But when i print , only one token is replaced.
After Token Replacement: {"media":[{"channels2":"[Token2]","channels":"22"}]}
Tried with various options like different prefix, suffix and token names. Nothing seems to work.

I think it is because of the nested [, the first token becomes [{\"channels2\":\"[Token2] which won't get replaced.
Without nesting I get:
Before Token Replacement: {"media":{"channels2":"[Token2]","channels":"[Token1]"}}
After Token Replacement: {"media":{"channels2":"33","channels":"22"}}
You should use a JSON processing library instead I guess.

Related

Comma(,) specified in file name makes curl processor fail to send a request

I have a Curl processor class which is used to send requests and get response as a plain string.
It worked like a charm, however recently I've encountered a problem. The problem has to do with sending multipart data. So, if there's a comma (perphaps other special character) specified in multipart body, it doesn't even send any request.
Here's what I mean (main method below)
public static String buildCurlProcessBuilderExecuteAndGetResponse(String httpMethod, String URL, List<String> headers, List<String> body, boolean includeResponseHeaders) throws IOException
{
List<String> finalCommands = new ArrayList<String>();
finalCommands.add("/usr/local/bin/curl");
finalCommands.add("-s");
finalCommands.add("-k");
if (includeResponseHeaders)
{
finalCommands.add("-i");
}
finalCommands.add("-X");
finalCommands.add(httpMethod);
finalCommands.add(URL);
if (headers != null)
{
finalCommands.addAll(headers);
}
if (body != null)
{
finalCommands.addAll(body);
}
ProcessBuilder pb = new ProcessBuilder(finalCommands);
pb.redirectErrorStream(true);
Process p = pb.start();
return getResponseAsString(p.getInputStream());
}
I add multipart body like so:
public static List<String> addMultipartBodyToCurlRequest(Map<String, String> mapOfheadersToAdd)
{
Iterator<Entry<String, String>> multipartBodyIt = mapOfheadersToAdd.entrySet().iterator();
List<String> bodyCommand = new ArrayList<String>();
while (multipartBodyIt.hasNext())
{
Map.Entry pair = (Map.Entry) multipartBodyIt.next();
bodyCommand.add(CURL_MULTIPART_BODY_IDENTIFIER); // "-F";
bodyCommand.add((String) pair.getKey() + "=" + (String) pair.getValue());
}
return bodyCommand;
}
I put the following properties to the body:
generatedBody.put("entityId", entityId);
generatedBody.put("SystemFolderID", systemFolderId);
generatedBody.put("resumableTotalSize", fileSize);
generatedBody.put("resumableFilename", fileName);
generatedBody.put("resumableRelativePath", fileName);
generatedBody.put("resumableIdentifier", fileUUID);
generatedBody.put("entityName", entityName);
generatedBody.put("resumableType", resumableType);
generatedBody.put("resumableTotalChunks", totalChunksSize);
And also
generatedBody.put("resumableChunkNumber", String.valueOf(i + 1));
generatedBody.put("resumableChunkSize", String.valueOf(chunkByteArray.length));
generatedBody.put("resumableCurrentChunkSize", String.valueOf(chunkByteArray.length));
generatedBody.put("file", "#" + currentChunk.getAbsolutePath() + ";" + "filename=" + fileName);
Then I call the method:
List<String> fileBody = CURLRequestProcessor.addMultipartBodyToCurlRequest(generatedBody);
And finally call
CURLRequestProcessor.buildCurlProcessBuilderExecuteAndGetResponse("POST", finalURL, generatedHeaders, fileBody, false)
But I don't get printed anything... It seems like one simple comma in the name of the file screwed everything up... It's used in the resumableFilename, resumableRelativePath and file parts.
Without comma in the name everything works. Is there a way to escape or do anything?
Btw, it's run on Ubuntu.
Almost forgot, PLEASE DON'T ASK ME WHY I'M USING CURL OVER any other HTTP client. I have to due to TLS
Thank you very much in advance!
HTTP headers support quoted strings that contain special characters. Try putting the values in quotes.
generatedBody.put("resumableRelativePath", "\"" + fileName + "\"");
If your file name contains a " character, you can escape it with a single backslash within the quoted string.
The solution turned out to be simple yet peculiar.
The problem had to do with this line:
generatedBody.put("file", "#" + currentChunk.getAbsolutePath() + ";" + "filename=" + fileName);
I changed it to:
generatedBody.put("file", "#" + currentChunk.getAbsolutePath());
Since I send the name of the file in 2 additional body parts called resumableFilename and resumableRelativePath, so specifying filename is redundant. In the latter comma screws up, while with these two parts comma doesn't matter
I wonder what if didn't have these though...

How do I guarantee that a name is valid Active directory user?

The goal is to extract different properties from an AD (active directory) using LDAP in java, given a list of user-IDs. For this, I have
public Map<String, List<String>> UserDetails(List<String> userSAMs){
DirContext ldapContext = null;
Map<String, List<String>> detailsMap = null;
ldapContext = new LdapProp().getLdapContext();
String returnedAtts[] = {"cn", "givenName", "memberOf"};
String searchFilter = "(&(objectClass=user)(|"; // long OR statement
for (String sam : listSamids){ // building the LDAP query
// HIC SUNT LEONES
searchFilter = "(" + sam + ")";
}
searchFilter = searchFilter + "))";
NamingEnumeration<SearchResult> answer = ldapContext.search(searchBase, searchFilter, searchCtls);
while (answer.hasMoreElements()) { // Loop over results
SearchResult sr = (SearchResult) answer.next();
Attributes attrs = sr.getAttributes();
String samStr= attrs.get("sAMAccountName").toString();
samStr.replace("sAMAccountName: ", "");
List<String> propOfSam = new ArrayList();
for (String ldapParam : returnedAtts){
String paramStr = attrs.get(ldapParam).toString();
paramStr.replace(ldapParam + ": ", ""); // extract value
propertiesOfSam.add(paramStr);
}
detailsMap.put(samStrng,propertiesOfSam);
};
return detailsMap;
}
For sake of simplicity, I stripped all error handling in the code. The class LdapProp encapsulates all the LDAP-connection details like PROVIDER_URL of the AD server, SECURITY_PRINCIPAL, SECURITY_CREDENTIALS, and the SEARCH_BASE.
My issue: How to I guarantee the sanity of the input list? The position for that is marked by HIC SUNT LEONES in the code.
The list of allowed characters is described in RFC 1779 and RFC 2253.
One thing I tried so far is to remove all forbidden characters from each string sam of the input list using a regular expression. The non-trivial part was how to correctly escape them. I came up with the following work-around: I replaced the line \\ HIC SUNT LEONES by
sam = sam.replaceAll("[\\\\<>=\\*+-;:\\|#\"\\[\\]\\?]" ,""));
Here, the outer square brackets is character class within the regex, i.e. [abc] means "any character from a,b or c". The tricky part is e.g. that \\\\ represents simply the backslash.

How to send plus operator in url in java

I am fetching data from server in my project. In some condition there is a need to send + operator in url with parameter. How can i send "+" in url with parameter.
here is my url
http://www.needsthesupermarket.com/webservice/dp/addCart.php?cart_id=43530&cust_id=13936&pid=11303&qty=1&combination=2 ltr + 1 kg&guest_id=2509245
In blank space i replace with %20. but problem with + sign. How can i send it in url?
%26 -> &
%2B -> +
You can decode/encode here
You should encode your GET parameters:
Uri.encode(someParam)
For example if you have some Map paramsGet with GET parameters:
final StringBuilder url = new StringBuilder("http://example.com");
String delim = "?";
for (final Map.Entry<String, String> entry : paramsGet.entrySet()) {
url.append(delim).append(entry.getKey()).append("=").append(Uri.encode(entry.getValue()));
delim = "&";
}
To Encode use
String encodedInput = java.net.URLEncoder.encode(inputText, "UTF-8");
To Decode use
String decodedInput = java.net.URLDecoder.decode(encodedInput, "UTF-8");

Parse a plain text into a Java Object

I´m parsing a plain text and trying to convert into an Object.
The text looks like(and i can´t change the format):
"N001";"2014-08-12-07.11.37.352000";" ";"some#email.com ";4847 ;"street";"NAME SURNAME ";26 ;"CALIFORNIA ";21
and The Object to convert:
String index;
String timestamp;
String mail;
Integer zipCode
...
I´ve tried with:
StringTokenizer st1 = new StringTokenizer(N001\";\"2014-08-12-07.11.37.352000\";\" \";\"some#email.com \";4847 ;\"street\";\"NAME SURNAME \";26 ;\"CALIFORNIA \";21);
while(st2.hasMoreTokens()) {
System.out.println(st2.nextToken(";").replaceAll("\"",""));
}
And the output is the correct one, i´ve thinking to have a counter and hardcoding with a case bucle and set the field deppending the counter, but the problem is that I have 40 fields...
Some idea?
Thanks a lot!
String line = "N001";"2014-08-12-07.11.37.352000";" ";"some#email.com ";4847 ;"street";"NAME SURNAME ";26 ;"CALIFORNIA ";21
StringTokenizer st1 = new StringTokenizer(line, ";");
while(st2.hasMoreTokens()) {
System.out.println(st2.nextToken().replaceAll("\"",""));
}
Or you can use split method and directly get a array of values using the delimiter ;
String []values = line.split(";");
then iterate through the array and get and cast the values they way you want
Regardless of the way you are parsing the file, you somehow need to define the mapping of column-to-field (and how to parse the text).
if this is a CVS file, you could use a library like super-csv. All you need to do is write a mapping definition.
I would first split your input String based on the semi-colon separator, then clean up the values.
For instance:
String input = "\"N001\";\"2014-08-12-07.11.37.352000\";\" " +
"\";\"some#email.com " +
"\";4847 ;\"street\";\"NAME " +
"SURNAME \";26 ;\"CALIFORNIA " +
"\";21 ";
// raw split
String[] split = input.split(";");
System.out.printf("Raw: %n%s%n", Arrays.toString(split));
// cleaning up whitespace and double quotes
ArrayList<String> cleanValues = new ArrayList<String>();
for (String s: split) {
String clean = s.replaceAll("[\\s\"]", "");
if (!clean.isEmpty()) {
cleanValues.add(clean);
}
}
System.out.printf("Clean: %n%s%n", cleanValues);
Output
Raw:
["N001", "2014-08-12-07.11.37.352000", " ", "some#email.com ", 4847 , "street", "NAME SURNAME ", 26 , "CALIFORNIA ", 21 ]
Clean:
[N001, 2014-08-12-07.11.37.352000, some#email.com, 4847, street, NAMESURNAME, 26, CALIFORNIA, 21]
Note
In order to map the values to your variables you will need to know their index in advance, and it will have to be consistent.
Then you can use the get(int i) method to retrieve them from your List - e.g. cleanValues.get(2) will get you the e-mail, etc.
Note (2)
If you do not know the indices in advance or they may vary, then you are in trouble.
You can of course try to get those indices by using regular expressions but I suspect you might end up complicating your life quite a bit.
you can use Java Reflection to automate your process.
Iterate over the fields
Field[] fields = dummyRow.getClass().getFields();
and set your values
SomeClass object = construct.newInstance();
field.set(object , value);

Find and replace token in string

Found lots of examples on string.replaceall but I cannot figure out how to use regex to solve my problem. I am looking to find and replace all occurrences of the string [reset_token] within my message.
Code I have so far:
String message = "Your new token is [reset_token]";
String newbody = replaceDelimiter("^[reset_token]", "mynewtoken");
public String replaceDelimiter(String delimiter, String message) {
return message.replaceAll(delimiter, message);
}
I would like the result to be "Your new token is mynewtoken"
You don't need replaceAll here, as your pattern is not really a regex, but is static. Simple replace would work fine:
String newbody = message.replace("[reset_token]", "mynewtoken");
And also you don't need that extra method wrapping your replace call.
You need replace() instead as it replaces the string token as is:
String message = "Your new token is [reset_token]";
String newbody = message.replace("[reset_token]", "mynewtoken");

Categories