get the values of the attribute userparameters from active directory - java

I need to get the values of the userparameters attribute. I use this code to connect to ldap, and with filters get the information I need. The problem is that userparameters contains values of several types, and you can not get them in the usual way, otherwise you will see this:
{userparameters=userParameters: PCtxCfgPresent????CtxCfgFlags1????CtxShadow????.CtxMaxDisconnectionTime????CtxMaxIdleTime????*CtxMinEncryptionLevel?
In this question in c #, the solution to my problem is described, IADsTSUserEx saves considerable time and makes the code less. Is there a similar solution on java? After much searching, I did not find anything. Thank you.

I finally managed to get my piece of Java code running to fulfill this need.
It's a direct port from this Powershell script : https://gist.github.com/HarmJ0y/08ee1824aa555598cff5efa4c5c96cf0
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.security.Security;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.directory.Attribute;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.Control;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.PagedResultsControl;
import javax.naming.ldap.PagedResultsResponseControl;
public class LDAP {
public static void main(String[] args) {
Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
InitialLdapContext ldapContext = null;
Hashtable ldapEnv = new Hashtable(11);
ldapEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
ldapEnv.put(Context.PROVIDER_URL, "ldaps://HOST:636");
ldapEnv.put(Context.SECURITY_AUTHENTICATION, "simple");
ldapEnv.put(Context.SECURITY_PROTOCOL, "ssl");
ldapEnv.put(Context.SECURITY_PRINCIPAL, "ADMIN");
ldapEnv.put(Context.SECURITY_CREDENTIALS, "PASSWORD");
ldapEnv.put("java.naming.ldap.attributes.binary", "objectGUID");
byte[] cookie = null;
String baseName = "BASENAME";
try {
ldapContext = new InitialLdapContext(ldapEnv, new Control[] { new PagedResultsControl(1, Control.NONCRITICAL) });
SearchControls ctls = new SearchControls();
ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
ctls.setCountLimit(1);
String[] attrs = new String[] { "objectGUID", "cn", "userParameters" };
ctls.setReturningAttributes(attrs);
NamingEnumeration<SearchResult> e = ldapContext.search(baseName, "(&(objectclass=user)(cn=USERCN))", ctls);
if (e.hasMore()) {
SearchResult sr = e.next();
Attribute attr = sr.getAttributes().get("cn");
if (attr.get() != null) {
NamingEnumeration<?> neAttr = attr.getAll();
while (neAttr.hasMoreElements()) {
String val = neAttr.next().toString();
System.out.println(val);
}
}
attr = sr.getAttributes().get("userParameters");
if (attr.get() != null) {
NamingEnumeration<?> neAttr = attr.getAll();
while (neAttr.hasMoreElements()) {
String v = neAttr.next().toString();
System.out.println("-------------");
byte[] val = v.getBytes(StandardCharsets.UTF_16LE);
ByteBuffer buffer = ByteBuffer.wrap(val);
buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.position(96);
char signature = buffer.getChar();
System.out.println("Signature : " + signature);
if (signature == 'P') {
int nbAttrs = (int) buffer.getChar();
System.out.println("nbAttrs : " + nbAttrs);
for (int i = 0; i < nbAttrs; i++) {
System.out.println("\n---- Attribute " + i + " ----");
int nameLength = (int) buffer.getChar();
System.out.println("nameLength : " + nameLength);
int valueLength = (int) buffer.getChar();
System.out.println("valueLength : " + valueLength);
int type = (int) buffer.getChar();
System.out.println("type : " + type);
byte[] attrNameTab = new byte[nameLength];
buffer.get(attrNameTab);
String attrName = new String(attrNameTab, StandardCharsets.UTF_16LE);
System.out.println("attrName : " + attrName);
byte[] attrValue = new byte[valueLength];
buffer.get(attrValue);
if (attrName.matches("CtxCfgPresent|CtxCfgFlags1|CtxCallBack|CtxKeyboardLayout|CtxMinEncryptionLevel|CtxNWLogonServer|CtxMaxConnectionTime|CtxMaxDisconnectionTime|CtxMaxIdleTime|CtxShadow")) {
String valueStr = "";
for (byte b : attrValue) {
valueStr += (char) b;
}
Integer valueInt = Integer.parseUnsignedInt(valueStr, 16);
System.out.println("attrValue : " + valueInt);
if (attrName.matches("CtxShadow")) {
switch (valueInt) {
case 0x0:
System.out.println(" -> Disable");
break;
case 0x1000000:
System.out.println(" -> EnableInputNotify");
break;
case 0x2000000:
System.out.println(" -> EnableInputNoNotify");
break;
case 0x3000000:
System.out.println(" -> EnableNoInputNotify");
break;
case 0x4000000:
System.out.println(" -> EnableNoInputNoNotify");
break;
}
} else if (attrName.matches("CtxCfgFlags1")) {
// this field is represented as a bitmask
for (CtxCfgFlagsBitValues en : CtxCfgFlagsBitValues.values()) {
if (en.isBit(valueInt)) {
System.out.println(" -> " + en.name());
}
}
} else if (attrName.matches("CtxMaxConnectionTime|CtxMaxDisconnectionTime|CtxMaxIdleTime")) {
for (CtxCfgFlagsTimeValues en : CtxCfgFlagsTimeValues.values()) {
if (en.getValue() == valueInt.intValue()) {
System.out.println(" -> " + en.name());
}
}
}
} else if (attrName.matches("CtxWFHomeDirDrive.*|CtxWFHomeDir.*|CtxWFHomeDrive.*|CtxInitialProgram.*|CtxWFProfilePath.*|CtxWorkDirectory.*|CtxCallbackNumber.*")) {
String str = new String(attrValue, StandardCharsets.US_ASCII);
String valueStr = convertHexToString(str);
valueStr = valueStr.substring(0, valueStr.length() - 1);
if (attrName.matches(".*W$")) {
// handle wide strings
valueStr = new String(new String(valueStr.getBytes(), StandardCharsets.US_ASCII).getBytes(),StandardCharsets.UTF_16LE);
valueStr = valueStr.substring(0, valueStr.length() - 1);
}
System.out.println("attrValue : " + valueStr);
}
}
}
}
}
Control[] controls = ldapContext.getResponseControls();
if (controls != null) {
for (int i = 0; i < controls.length; i++) {
if (controls[i] instanceof PagedResultsResponseControl) {
PagedResultsResponseControl prrc = (PagedResultsResponseControl) controls[i];
cookie = prrc.getCookie();
} else {
// Handle other response controls (if any)
}
}
}
ldapContext.setRequestControls(new Control[] { new PagedResultsControl(1, cookie, Control.CRITICAL) });
}
while (cookie != null);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (ldapContext != null) {
try {
ldapContext.close();
} catch (Exception e1) {
}
}
}
}
public static String convertHexToString(String hex) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hex.length() - 1; i += 2) {
// grab the hex in pairs
String output = hex.substring(i, (i + 2));
// convert hex to decimal
int decimal = Integer.parseInt(output, 16);
// convert the decimal to character
sb.append((char) decimal);
}
return sb.toString();
}
private static enum CtxCfgFlagsBitValues {
INHERITCALLBACK(0x08000000),
INHERITCALLBACKNUMBER(0x04000000),
INHERITSHADOW(0x02000000),
INHERITMAXSESSIONTIME(0x01000000),
INHERITMAXDISCONNECTIONTIME(0x00800000),
INHERITMAXIDLETIME(0x00400000),
INHERITAUTOCLIENT(0x00200000),
INHERITSECURITY(0x00100000),
PROMPTFORPASSWORD(0x00080000),
RESETBROKEN(0x00040000),
RECONNECTSAME(0x00020000),
LOGONDISABLED(0x00010000),
AUTOCLIENTDRIVES(0x00008000),
AUTOCLIENTLPTS(0x00004000),
FORCECLIENTLPTDEF(0x00002000),
DISABLEENCRYPTION(0x00001000),
HOMEDIRECTORYMAPROOT(0x00000800),
USEDEFAULTGINA(0x00000400),
DISABLECPM(0x00000200),
DISABLECDM(0x00000100),
DISABLECCM(0x00000080),
DISABLELPT(0x00000040),
DISABLECLIP(0x00000020),
DISABLEEXE(0x00000010),
WALLPAPERDISABLED(0x00000008),
DISABLECAM(0x00000004);
private int mask;
CtxCfgFlagsBitValues(int mask) {
this.mask = mask;
}
public boolean isBit(int val) {
return ((val & mask) == mask);
}
}
private static enum CtxCfgFlagsTimeValues {
ONE_MINUTE(1625948160),
FIVE_MINUTES(-527236096),
TEN_MINUTES(-1071183616),
FIFTEEN_MINUTES(-1598354176),
THIRTY_MINUTES(1081547520),
ONE_HOUR(-2131872256),
TWO_HOURS(14511360),
THREE_HOURS(-2134137856),
ONE_DAY(6039045),
TWO_DAYS(12078090);
private int value;
CtxCfgFlagsTimeValues(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
}

Related

Retrieving sidHistory from LDAP with Java

I can retrieve objectSID and many other attributes without error, but not sidHistory (I need sidHistory to see which account in domain A corresponds to an account in domain B).
Here's the code that works for most attributes, including objectSID:
void dumpCSV(Attributes attrs, String[] displayList, Logger lg) {
// Assume we're only dealing with single valued attributes (for now)
StringBuilder sb = new StringBuilder();
for (String attName : displayList) {
String name = attName.trim().toLowerCase();
Attribute att = attrs.get(name);
if (sb.length() > 0)
sb.append(",");
if (att != null) {
String v = "?";
try {
if ((name.equals("objectsid")) || (name.equals("sidhistory")))
v = binString(att);
else {
v = (String) att.get();
if (name.equals("pwdlastset") || name.equals("lastlogontimestamp") || name.equals("lastlogon") || name.equals("accountexpires"))
v = TickConverter.tickDate(v);
}
sb.append(Logger.tidyString(v));
} catch (NamingException e) {
System.err.println("NamingException, " + e);
return;
}
}
}
lg.logln(sb.toString());
}
}
static String binString(Attribute att) {
try {
byte bin[] = (byte[]) att.get();
return decodeSID(bin);
} catch (NamingException e) {
System.err.println("NamingException, " + e);
return "?";
}
}
// taken from http://www.adamretter.org.uk/blog/entries/LDAPTest.java, in turn borrowed from Oracle docs
public static String decodeSID(byte[] sid) {
final StringBuilder strSid = new StringBuilder("S-");
// get version
final int revision = sid[0];
strSid.append(Integer.toString(revision));
//next byte is the count of sub-authorities
final int countSubAuths = sid[1] & 0xFF;
//get the authority
long authority = 0;
//String rid = "";
for(int i = 2; i <= 7; i++) {
authority |= ((long)sid[i]) << (8 * (5 - (i - 2)));
}
strSid.append("-");
strSid.append(Long.toHexString(authority));
//iterate all the sub-auths
int offset = 8;
int size = 4; //4 bytes for each sub auth
for(int j = 0; j < countSubAuths; j++) {
long subAuthority = 0;
for(int k = 0; k < size; k++) {
subAuthority |= (long)(sid[offset + k] & 0xFF) << (8 * k);
}
strSid.append("-");
strSid.append(subAuthority);
offset += size;
}
return strSid.toString();
}
If I try to retrieve sidHistory using this, tyhe value I get is "?".
Even if I use a namingEnumeration, as I think I probably should, I get "Exception in thread "AWT-EventQueue-0" java.util.NoSuchElementException: Vector Enumeration", probably because I am trying to save it to the wrong typoe (and I've tried a few different types).
snippet is :
String v;
NamingEnumeration nenum = att.getAll();
while (nenum.hasMore()) {
v = "";
if (name.equals("objectsid")) {
v = binString(att);
nenum.next();
} else if (name.equals("sidhistory")) {
nenum.next();
String[] vv = ((String[]) nenum.next());
v = vv[0];
} else
v = (String) nenum.next();
if (name.equals("pwdlastset") || name.equals("lastlogontimestamp") || name.equals("lastlogon") || name.equals("accountexpires"))
v = TickConverter.tickDate(v);
lg.logln(name + "=" + Logger.tidyString(v));
}
We used some code similar to:
We note we saw it at http://tomcatspnegoad.sourceforge.net/xref/net/sf/michaelo/tomcat/realm/ActiveDirectoryRealm.html#L566
...
Attribute sidHistory = roleAttributes.get("sIDHistory;binary");
List<String> sidHistoryStrings = new LinkedList<String>();
if (sidHistory != null)
{
NamingEnumeration<?> sidHistoryEnum = sidHistory.getAll();
while (sidHistoryEnum.hasMore())
{
byte[] sidHistoryBytes = (byte[]) sidHistoryEnum.next();
sidHistoryStrings.add(new Sid(sidHistoryBytes).toString());
}
...
}
sidHistory is multi-valued and binary (octetString) is what cause most people headaches.
Hope this helps.

Exception in thread "main" java.lang.IllegalArgumentException: bound must be positive

import java.util.Random;
import java.util.StringTokenizer;
public class FortuneCookie {
private String subjList;
private String objList;
private String verbList;
private int sWords = 0;
private int oWords = 0;
private int vWords = 0;
private Random random = new Random();
public FortuneCookie() {
subjList = "i#You#He#She#It#They";
objList = "me#you#him#her#it#them";
verbList = "hate#love#deny#find#hear#forgive#hurt#win#teach";
}
public void setSubject(String subj) {
subjList = subj;
}
public void setObjectList(String obj) {
objList = obj;
}
public void setVerbList(String verb) {
verbList = verb;
}
public String genFortuneMsg() {
String v = " ";
String o = " ";
String s = " ";
StringTokenizer st1 = new StringTokenizer(subjList, "#");
StringTokenizer st2 = new StringTokenizer(objList, "#");
StringTokenizer st3 = new StringTokenizer(verbList, "#");
while (st1.hasMoreTokens()) {
s = st1.nextToken();
sWords = st1.countTokens();
int no = random.nextInt(sWords);
if (no == sWords) {
break;
}
}
while (st2.hasMoreTokens()) {
o = st2.nextToken();
oWords = st2.countTokens();
int no2 = random.nextInt(oWords);
if (no2 == oWords) {
break;
}
}
while (st3.hasMoreTokens()) {
v = st3.nextToken();
vWords = st3.countTokens();
int no3 = random.nextInt(vWords);
if (no3 == vWords) {
break;
}
}
String gen = s + " " + v + " " + o;
return gen;
}
public void print() {
System.out.println("Tokens");
System.out.println("Subject List:" + subjList + " count = " + sWords);
System.out.println("verb List:" + verbList + " count = " + vWords);
System.out.println("object List:" + objList + " count = " + oWords);
}
}
Exception in thread "main" java.lang.IllegalArgumentException: bound
must be positive at java.util.Random.nextInt(Random.java:388) at
FortuneCookie.genFortuneMsg(FortuneCookie.java:42) at
FortuneCookieTest.main(FortuneCookieTest.java:6)
Your case is not negative it is zero.
From the docs of countToken method
/**
* Calculates the number of times that this tokenizer's
* <code>nextToken</code> method can be called before it generates an
* exception. The current position is not advanced.
*
In a while loop when your count token return zero, you run into an exception. Well that error message should be reformatted to negative or zero.
Add 1 to your result or check for zero. Should work.

SVM Predict reading datatest

I have such a big problem with implementation the svm_predict function. I have trained svm, and prepare datatest. Both files are in .txt. file.Datatest are from LBP( Local Binary patterns) and it looks like:
-0.6448744548418511
-0.7862774302452588
1.7746263060948377
I'm loading it to the svm_predict function and at my console after compiling my program there is:
Accuracy = 0.0% (0/800) (classification)
So it's look like it can't read datatest?
import libsvm.*;
import java.io.*;
import java.util.*;
class svm_predict {
private static double atof(String s)
{
return Double.valueOf(s).doubleValue();
}
private static int atoi(String s)
{
return Integer.parseInt(s);
}
private static void predict(BufferedReader input, DataOutputStream output, svm_model model, int predict_probability) throws IOException
{
int correct = 0;
int total = 0;
double error = 0;
double sumv = 0, sumy = 0, sumvv = 0, sumyy = 0, sumvy = 0;
int svm_type=svm.svm_get_svm_type(model);
int nr_class=svm.svm_get_nr_class(model);
double[] prob_estimates=null;
if(predict_probability == 1)
{
if(svm_type == svm_parameter.EPSILON_SVR ||
svm_type == svm_parameter.NU_SVR)
{
System.out.print("Prob. model for test data: target value = predicted value + z,\nz: Laplace distribution e^(-|z|/sigma)/(2sigma),sigma="+svm.svm_get_svr_probability(model)+"\n");
}
else
{
int[] labels=new int[nr_class];
svm.svm_get_labels(model,labels);
prob_estimates = new double[nr_class];
output.writeBytes("labels");
for(int j=0;j<nr_class;j++)
output.writeBytes(" "+labels[j]);
output.writeBytes("\n");
}
}
while(true)
{
String line = input.readLine();
if(line == null) break;
StringTokenizer st = new StringTokenizer(line," \t\n\r\f:");
double target = atof(st.nextToken());
int m = st.countTokens()/2;
svm_node[] x = new svm_node[m];
for(int j=0;j<m;j++)
{
x[j] = new svm_node();
x[j].index = atoi(st.nextToken());
x[j].value = atof(st.nextToken());
}
double v;
if (predict_probability==1 && (svm_type==svm_parameter.C_SVC || svm_type==svm_parameter.NU_SVC))
{
v = svm.svm_predict_probability(model,x,prob_estimates);
output.writeBytes(v+" ");
for(int j=0;j<nr_class;j++)
output.writeBytes(prob_estimates[j]+" ");
output.writeBytes("\n");
}
else
{
v = svm.svm_predict(model,x);
output.writeBytes(v+"\n");
}
if(v == target)
++correct;
error += (v-target)*(v-target);
sumv += v;
sumy += target;
sumvv += v*v;
sumyy += target*target;
sumvy += v*target;
++total;
}
if(svm_type == svm_parameter.EPSILON_SVR ||
svm_type == svm_parameter.NU_SVR)
{
System.out.print("Mean squared error = "+error/total+" (regression)\n");
System.out.print("Squared correlation coefficient = "+
((total*sumvy-sumv*sumy)*(total*sumvy-sumv*sumy))/
((total*sumvv-sumv*sumv)*(total*sumyy-sumy*sumy))+
" (regression)\n");
}
else
System.out.print("Accuracy = "+(double)correct/total*100+
"% ("+correct+"/"+total+") (classification)\n");
}
private static void exit_with_help()
{
System.err.print("usage: svm_predict [options] test_file model_file output_file\n"
+"options:\n"
+"-b probability_estimates: whether to predict probability estimates, 0 or 1 (default 0); one-class SVM not supported yet\n");
System.exit(1);
}
public static void main(String argv[]) throws IOException
{
int i, predict_probability=0;
// parse options
for(i=0;i<argv.length;i++)
{
if(argv[i].charAt(0) != '-') break;
++i;
switch(argv[i-1].charAt(1))
{
case 'b':
predict_probability = atoi(argv[i]);
break;
default:
System.err.print("Unknown option: " + argv[i-1] + "\n");
exit_with_help();
}
}
if(i>=argv.length-2)
exit_with_help();
try
{
BufferedReader input = new BufferedReader(new FileReader(argv[i]));
DataOutputStream output = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(argv[i+2])));
svm_model model = svm.svm_load_model(argv[i+1]);
if(predict_probability == 1)
{
if(svm.svm_check_probability_model(model)==0)
{
System.err.print("Model does not support probabiliy estimates\n");
System.exit(1);
}
}
else
{
if(svm.svm_check_probability_model(model)!=0)
{
System.out.print("Model supports probability estimates, but disabled in prediction.\n");
}
}
predict(input,output,model,predict_probability);
input.close();
output.close();
}
catch(FileNotFoundException e)
{
exit_with_help();
}
catch(ArrayIndexOutOfBoundsException e)
{
exit_with_help();
}
}
}
It's difficult to know becasue its a big process
make sure you follow their classification guide
the data should be scaled it seems it goes above 1 right now

java parsing of complex string?

I am getting a string response from server like this..
[
Anchor{anchorName='&loreal_lip_balm',
clientName='loreal india',
anchorPrice=10,
campaigns=[
Campaign{
campaignId='loreal_camp1',
question='How to Turn Your Melted Lipstick into a Tinted Lip Balm',
startDate=2015-08-04,
endDate=2015-08-04,
imageURL='null',
regionCountry='ALL',
rewardInfo='null',
campaignPrice=20,
options=null
}
]},
Anchor{
anchorName='&loreal_total_repair_5',
clientName='loreal india',
anchorPrice=125,
campaigns=[
Campaign{
campaignId='loreal_camp2',
question='Is it a good
product to buy?',
startDate=2015-08-04,
endDate=2015-08-04,
imageURL='null',
regionCountry='ALL',
rewardInfo='null',
campaignPrice=20,
options=null
}
]
}
].
can anybody tell me how to parse this.It is not a json response.
I used hand coded parsers for simple languages where I felt that using http://www.antlr.org/ or https://javacc.java.net to be a bit heavy. I used the same structure for parsing JSON, CSS a simple template. Modified it to parse your response. See whether it helps.
package snippet;
import java.io.IOException;
import java.io.PushbackReader;
import java.io.Reader;
import java.io.StringReader;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import snippet.RecursiveDescentParser.Token.TokenType;
public class RecursiveDescentParser {
// #formatter:off
final static String text = "" +
"[" +
" Anchor{anchorName='&loreal_lip_balm'," +
" clientName='loreal india'," +
"" +
" anchorPrice=10," +
" campaigns=[" +
" Campaign{" +
" campaignId='loreal_camp1'," +
"" +
" question='How to Turn Your Melted Lipstick into a Tinted Lip Balm'," +
"" +
" startDate=2015-08-04," +
" endDate=2015-08-04," +
" imageURL='null'," +
"" +
" regionCountry='ALL'," +
" rewardInfo='null'," +
" campaignPrice=20," +
"" +
" options=null" +
" }" +
" ]}," +
" Anchor{" +
"" +
" anchorName='&loreal_total_repair_5'," +
" clientName='loreal india'," +
" anchorPrice=125," +
"" +
" campaigns=[" +
" Campaign{" +
" campaignId='loreal_camp2'," +
" question='Is it a good" +
" product to buy?'," +
" startDate=2015-08-04," +
" endDate=2015-08-04," +
"" +
" imageURL='null'," +
" regionCountry='ALL'," +
" rewardInfo='null'," +
"" +
" campaignPrice=20," +
" options=null" +
" }" +
" ]" +
" }" +
" ]" +
"";
// #formatter:on
static class Token {
enum TokenType {
OPEN_BRACKET, CLOSE_BRACKET, OPEN_BRACE, CLOSE_BRACE, STRING, NAME, COMMA, EQUALS, INTEGER, DATE, EOF, NULL;
}
private String text;
private TokenType type;
public Token(TokenType type) {
this(type, null);
}
public Token(TokenType type, String text) {
this.type = type;
this.text = text;
}
public TokenType getType() {
return type;
}
public String getText() {
return text;
}
#Override public String toString() {
return "Token [text=" + text + ", type=" + type + "]";
}
}
static class TokenReader {
private PushbackReader reader;
public TokenReader(Reader reader) {
this.reader = new PushbackReader(reader);
}
public Token nextToken() throws IOException {
Token t = nextTokenx();
System.out.println("Got: " + t);
return t;
}
public Token nextTokenx() throws IOException {
int c;
while ((c = reader.read()) != -1 && Character.isWhitespace((char) c))
;
if (c == -1)
return new Token(TokenType.EOF);
switch (c) {
case '[':
return new Token(TokenType.OPEN_BRACKET);
case ']':
return new Token(TokenType.CLOSE_BRACKET);
case '{':
return new Token(TokenType.OPEN_BRACE);
case '}':
return new Token(TokenType.CLOSE_BRACE);
case ',':
return new Token(TokenType.COMMA);
case '=':
return new Token(TokenType.EQUALS);
default:
if (Character.isDigit(c))
return readIntegerOrDate(c);
if (c == '\'')
return readString(c);
if (Character.isJavaIdentifierStart(c))
return readName(c);
throw new RuntimeException("Invalid character '" + ((char) c) + "' in input");
}
}
private Token readName(int c) throws IOException {
StringBuilder sb = new StringBuilder();
sb.append((char) c);
while ((c = reader.read()) != -1 && Character.isJavaIdentifierPart(c))
sb.append((char) c);
if (c != -1)
reader.unread(c);
if ("null".equals(sb.toString()))
return new Token(TokenType.NULL);
return new Token(TokenType.NAME, sb.toString());
}
private Token readString(int end) throws IOException {
StringBuilder sb = new StringBuilder();
int c;
while ((c = reader.read()) != -1 && c != end)
sb.append((char) c);
return new Token(TokenType.STRING, sb.toString());
}
private Token readIntegerOrDate(int c) throws IOException {
StringBuilder sb = new StringBuilder();
sb.append((char) c);
while ((c = reader.read()) != -1 && Character.isDigit((char) c))
sb.append((char) c);
if (c == '-') {
sb.append((char) c);
return readDate(sb);
}
if (c != -1)
reader.unread(c);
return new Token(TokenType.INTEGER, sb.toString());
}
private Token readDate(StringBuilder sb) throws IOException {
int c;
while ((c = reader.read()) != -1 && Character.isDigit((char) c))
sb.append((char) c);
if (c == -1)
throw new RuntimeException("EOF while reading date");
if (c != '-')
throw new RuntimeException("Invalid character '" + (char) c + "' while reading date");
sb.append((char) c);
while ((c = reader.read()) != -1 && Character.isDigit((char) c))
sb.append((char) c);
if (c != -1)
reader.unread(c);
return new Token(TokenType.DATE, sb.toString());
}
}
static class Lexer {
private TokenReader reader;
private Token current;
public Lexer(Reader reader) {
this.reader = new TokenReader(reader);
}
public Token expect(TokenType... tt) throws IOException {
if (current == null)
current = reader.nextToken();
for (TokenType tokenType : tt) {
if (current.getType() == tokenType) {
Token r = current;
current = null;
return r;
}
}
throw new RuntimeException("Expecting one of " + Arrays.asList(tt) + " but got " + current);
}
public Token expect1or0(TokenType... tt) throws IOException {
if (current == null)
current = reader.nextToken();
for (TokenType tokenType : tt) {
if (current.getType() == tokenType) {
Token r = current;
current = null;
return r;
}
}
return null;
}
}
public Object parse(String text) throws IOException {
return parse(new StringReader(text));
}
private Object parse(Reader reader) throws IOException {
Lexer lexer = new Lexer(reader);
return parse(lexer);
}
private Object parse(Lexer lexer) throws IOException {
Token t = lexer.expect1or0(TokenType.OPEN_BRACE, TokenType.OPEN_BRACKET, TokenType.EOF);
if (t == null || t.getType() == TokenType.EOF)
return null;
else if (t.getType() == TokenType.OPEN_BRACKET) {
return parseList(lexer);
} else {
return parseMap(null, lexer);
}
}
private List<Object> parseList(Lexer lexer) throws IOException {
ArrayList<Object> result = new ArrayList<Object>();
Token tName = lexer.expect1or0(TokenType.NAME);
while (tName != null) {
lexer.expect(TokenType.OPEN_BRACE);
result.add(parseMap(tName.getText(), lexer));
if (lexer.expect1or0(TokenType.COMMA) != null)
tName = lexer.expect(TokenType.NAME);
else
tName = null;
}
lexer.expect(TokenType.CLOSE_BRACKET);
return result;
}
private Object parseMap(String oname, Lexer lexer) throws IOException {
Map<String, Object> result = new HashMap<String, Object>();
if (oname != null)
result.put("objectName", oname);
Token tName = lexer.expect1or0(TokenType.NAME);
while (tName != null) {
String name = tName.getText();
lexer.expect(TokenType.EQUALS);
Token next = lexer.expect(TokenType.STRING, TokenType.DATE, TokenType.INTEGER, TokenType.OPEN_BRACKET,
TokenType.OPEN_BRACE, TokenType.NULL);
TokenType tt = next.getType();
if (tt == TokenType.STRING) {
result.put(name, next.getText());
} else if (tt == TokenType.DATE) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
result.put(name, sdf.parse(next.getText()));
} catch (ParseException e) {
return new RuntimeException(e);
}
} else if (tt == TokenType.INTEGER) {
result.put(name, Integer.valueOf(next.getText()));
} else if (tt == TokenType.OPEN_BRACKET) {
result.put(name, parseList(lexer));
} else if (tt == TokenType.OPEN_BRACE) {
result.put(name, parseMap(null, lexer));
} else {
result.put(name, null);
}
if (lexer.expect1or0(TokenType.COMMA) != null)
tName = lexer.expect(TokenType.NAME);
else
tName = null;
}
lexer.expect(TokenType.CLOSE_BRACE);
return result;
}
public static void main(String[] args) throws IOException {
RecursiveDescentParser parser = new RecursiveDescentParser();
Object o = parser.parse(text);
System.out.println(o);
}
}
Here is my suggestion.
I assume as you said that your input from the server is String.
I have build a little method that return the value of the required key.
public String valueFinder(String data, String key){
int keyValueStart = data.indexOf(key) + key.length() + 1;
String keyValueRaw = data.substring(keyValueStart, data.length());
int keyValueEnd = keyValueRaw.indexOf(",");
String keyValue = keyValueRaw.substring(0, keyValueEnd);
String value = keyValue.replaceAll("^\'|\'$", "");
return value;
}
So if you pass the String data generated by the server to the method and the ask for the required key for example for "clientName" it will return loreal india, if you pass/look-for "anchorName" it will return &loreal_lip_balm.
Now you have the concept, you are welcome to change/modify/customize it as you wish to fetch more detailed information in your campaigns or other scenarios.
It is possible to further develop the method to return single key value, a set of keys and values, convert keys and values to JSON or Array, and just name it.
All this can be done on the same concept.
There is a tool called ANTLR which is useful to read data like this.

JPA wrapper to convert unchecked exceptions into checked exceptions?

Before I wander off and re-create the wheel, does anyone know of a JPA wrapper that turns the unchecked exceptions JPA throws into checked exceptions?
Not looking for an argument about why I should not want checked exceptions, I do want them :-)
You can do 99% of rolling your own using the code below. It will leave you with two compile errors due to the members of a Collection needing to be encapsulated, but it does take you past the point where it is no longer worth automating.
package so;
import javax.persistence.*;
import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.*;
public class CheckedPersistenceMaker {
static final String PACKAGE = "stackoverflow.javax.persistence";
static final String PACKAGE_DIR = PACKAGE.replace('.', '/');
static Class<?>[] CLASSES = new Class<?>[] { Cache.class,
EntityManager.class, EntityManagerFactory.class,
EntityTransaction.class, Parameter.class,
PersistenceUnitUtil.class, PersistenceUtil.class,
Persistence.class, Query.class, Tuple.class, TupleElement.class,
TypedQuery.class };
private static String getName(Class<?> c) {
String name = c.getName();
for(Class<?> p:CLASSES) {
if (p.equals(c))
return PACKAGE + ".Checked"
+ name.substring(name.lastIndexOf('.') + 1);
}
return c.getName();
}
static void generateWrapper(Class<?> c) throws Exception {
String name = c.getName();
TypeVariable<?>[] genType = c.getTypeParameters();
String varNames = "";
if (genType != null && genType.length != 0) {
StringBuilder b = new StringBuilder();
b.append("<");
for(int i = 0;i < genType.length;i++) {
if (i > 0) b.append(",");
b.append(genType[i].getName());
}
b.append(">");
varNames = b.toString();
}
name = "Checked" + name.substring(name.lastIndexOf('.') + 1);
File javaFile = new File(PACKAGE_DIR + "/" + name + ".java");
javaFile.getParentFile().mkdirs();
FileWriter w = new FileWriter(javaFile);
w.write("package " + PACKAGE + ";\n");
w.write("public class " + name + varNames + " {\n");
w.write(" private final " + c.getName() + varNames
+ " wrapped;\n\n ");
w.write(name + "(" + c.getName() + varNames
+ " original) {\nwrapped=original;\n}\n\n");
w.write(" public " + c.getName() + varNames
+ " getOriginal() { return wrapped; }\n\n");
Method[] ms = c.getDeclaredMethods();
for(Method m:ms) {
if (!Modifier.isPublic(m.getModifiers())) continue;
w.write(" ");
String s = m.toGenericString();
s = s.replace(" abstract ", " ");
s = s.replace(c.getName() + ".", "");
String q = s.substring(0, s.indexOf('('));
if (q.indexOf('<',10) != -1) q = q.substring(0, q.indexOf('<',10));
boolean needsTranslate = false;
for(Class<?> cc:CLASSES) {
String ccn = cc.getName();
if (q.indexOf(ccn) != -1) needsTranslate = true;
String ccc = ccn.replace(cc.getPackage().getName() + ".",
PACKAGE + ".Checked");
s = s.replace(ccn, ccc);
}
int pc = 0;
int p = s.indexOf('(');
if (s.charAt(p + 1) != ')') {
StringBuilder b = new StringBuilder(s);
int g = 0;
char ch;
do {
ch = b.charAt(p);
switch (ch) {
case '<': {
g++;
break;
}
case '>': {
g--;
break;
}
case ',':
case ')': {
if (g == 0) {
String pa = " p" + pc;
b.insert(p, pa);
pc++;
p += pa.length();
}
break;
}
}
p++;
} while( ch != ')' );
s = b.toString();
}
w.write(s);
w.write(" throws CheckedPersistenceException");
Class<?>[] excs = m.getExceptionTypes();
for(Class<?> e:excs) {
w.write(", " + e.getName());
}
w.write(" {\n try {\n ");
Class<?> ret = m.getReturnType();
if (!ret.equals(Void.TYPE)) {
w.write("return ");
if (needsTranslate) {
String retName = ret.getName();
retName = retName.replace(c.getPackage().getName() + ".",
PACKAGE + ".Checked");
w.write("new " + retName + "(");
}
}
if (Modifier.isStatic(m.getModifiers())) {
w.write(c.getName() + "." + m.getName() + "(");
} else {
w.write("wrapped." + m.getName() + "(");
}
Class<?> paramTypes[] = m.getParameterTypes();
for(int i = 0;i < pc;i++) {
if (i > 0) w.write(',');
boolean isChecked = false;
for(int j=0;j<CLASSES.length;j++) {
if( CLASSES[j].equals(paramTypes[i]) ) isChecked=true;
}
w.write("p" + i);
if(isChecked) w.write(".getOriginal()");
}
w.write(')');
if (needsTranslate) w.write(')');
w.write(";\n } catch ( javax.persistence.PersistenceException e ) { throw new CheckedPersistenceException(e); }\n }\n\n");
}
w.write("}\n");
w.close();
}
public static void main(String[] args) throws Exception {
for(Class<?> c:CLASSES) {
generateWrapper(c);
}
}
}

Categories

Resources