Most of my blogs are just reminders to myself. When you want to copy a file from one location to another, with Java 7+ you can use the java.nio.file classes to accomplish this.
I'll post some of my own code here later, but here's an example I am going to just include as a reference:
http://www.javapractices.com/topic/TopicAction.do?Id=246
Thanks for viewing my blog on Identity Management and Engineering (mostly IDM). Please follow and check out the advertisers.
Search This Blog
Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts
Sunday, March 25, 2018
Thursday, April 9, 2015
Constructing the Shuffle Algorithm
I recently needed to perform a shuffle operation on a set. Shuffling seems very easy, but it actually can be difficult and fraught with errors. Here's some info on how I went from the start to the finish of the development of my shuffle algorithm.
Like shuffling a deck of cards, a shuffle operation does not change the frequency of the values found in the set or list. The shuffle operation can apply to a set or a list. Recalling that a set consists of only unique values (no repeats) and a list consists of values and so, it can contain duplicates. No matter what the source, the algorithm is the same.
The algorithm requires a random number generator (I will use Java):
Random random=new Random(System.currentTimeMillis());
int ranvalue=0;
int ranloc=0;
for(ranloc=0; ranloc<1000; ranloc++) {
ranvalue=random.nextInt(1000);
}
I always set up a number generator as I show above, to properly seed the generator and then "spin" it 1000 times to get the random number generator properly set up.
Here is the basic starting setup and algorithm.
List<String> sourceList = new ArrayList<String>();
populate sourceList from the source.
List<String> shuffleList = new ArrayList<String>();
add the values from the sourceList to the shuffleList in a shuffled order.
This method:
shuffleList.addAll(sourceList)
would not be a good idea, the data are copied in the same order.
Using this method:
int numSource=sourceList.size();
for(ranloc=0; ranloc<numSource; ranloc++) {
ranvalue=random.nextInt(numSource);
shuffleList.add(sourceList.get(ranvalue);
}
This method would randomize the values, but depending on the size of the source list, there is a high likelyhood of the shuffleList containing the source data in different frequencies, as there is a high probablility of the random.nextInt call returning the same value in two calls. This method is flawed.
You could add a list of used values:
int numSource=sourceList.size();
List<Integer> usedLocations=new ArrayList<Integer>();
Integer usedLocation=null;
for(ranloc=0; ranloc<numSource; ranloc++) {
ranvalue=random.nextInt(numSource);
usedLocation=new Integer(ranvalue);
while(usedLocations.contains(usedLocation) {
ranvalue=random.nextInt(numSource);
usedLocation=new Integer(ranvalue);
}
shuffleList.add(sourceList.get(ranvalue);
usedLocations.add(usedLocation);
}
This will work, but can get into a very long spin of the while loop as the shuffleList fills up, looking for that one value that has not been filled in.
The better way is to use a use and delete method:
int numSource=sourceList.size();
List<Integer> unusedLocations=new ArrayList<Integer>();
Integer usedLocation=null;
int numLocations=numSource;
for(ranloc=0; ranloc<numSource; ranloc++) {
usedLocation=new Integer(ranloc);
unusedLocations.add(usedLocation);
}
for(ranloc=0; ranloc<numSource; ranloc++) {
ranvalue=random.nextInt(numLocations);
usedLocation=unusedLocations.get(ranvalue);
ranvalue=usedLocations.intValue();
shuffleList.add(sourceList.get(ranvalue);
usedLocations.remove(usedLocation);
numLocations=unusedLocations.size();
}
This method works properly and has a good speed.
Happy Shuffling!
Like shuffling a deck of cards, a shuffle operation does not change the frequency of the values found in the set or list. The shuffle operation can apply to a set or a list. Recalling that a set consists of only unique values (no repeats) and a list consists of values and so, it can contain duplicates. No matter what the source, the algorithm is the same.
The algorithm requires a random number generator (I will use Java):
Random random=new Random(System.currentTimeMillis());
int ranvalue=0;
int ranloc=0;
for(ranloc=0; ranloc<1000; ranloc++) {
ranvalue=random.nextInt(1000);
}
I always set up a number generator as I show above, to properly seed the generator and then "spin" it 1000 times to get the random number generator properly set up.
Here is the basic starting setup and algorithm.
List<String> sourceList = new ArrayList<String>();
populate sourceList from the source.
List<String> shuffleList = new ArrayList<String>();
add the values from the sourceList to the shuffleList in a shuffled order.
This method:
shuffleList.addAll(sourceList)
would not be a good idea, the data are copied in the same order.
Using this method:
int numSource=sourceList.size();
for(ranloc=0; ranloc<numSource; ranloc++) {
ranvalue=random.nextInt(numSource);
shuffleList.add(sourceList.get(ranvalue);
}
This method would randomize the values, but depending on the size of the source list, there is a high likelyhood of the shuffleList containing the source data in different frequencies, as there is a high probablility of the random.nextInt call returning the same value in two calls. This method is flawed.
You could add a list of used values:
int numSource=sourceList.size();
List<Integer> usedLocations=new ArrayList<Integer>();
Integer usedLocation=null;
for(ranloc=0; ranloc<numSource; ranloc++) {
ranvalue=random.nextInt(numSource);
usedLocation=new Integer(ranvalue);
while(usedLocations.contains(usedLocation) {
ranvalue=random.nextInt(numSource);
usedLocation=new Integer(ranvalue);
}
shuffleList.add(sourceList.get(ranvalue);
usedLocations.add(usedLocation);
}
This will work, but can get into a very long spin of the while loop as the shuffleList fills up, looking for that one value that has not been filled in.
The better way is to use a use and delete method:
int numSource=sourceList.size();
List<Integer> unusedLocations=new ArrayList<Integer>();
Integer usedLocation=null;
int numLocations=numSource;
for(ranloc=0; ranloc<numSource; ranloc++) {
usedLocation=new Integer(ranloc);
unusedLocations.add(usedLocation);
}
for(ranloc=0; ranloc<numSource; ranloc++) {
ranvalue=random.nextInt(numLocations);
usedLocation=unusedLocations.get(ranvalue);
ranvalue=usedLocations.intValue();
shuffleList.add(sourceList.get(ranvalue);
usedLocations.remove(usedLocation);
numLocations=unusedLocations.size();
}
This method works properly and has a good speed.
Happy Shuffling!
Wednesday, February 26, 2014
OIM 11gR2 How to make plugins easier to manage
Making plugins easier to manage is simple. I have a prior post that is not as detailed but is still applicable. First, occasionally run this query against your database and export the results:
SELECT DISTINCT(ID) FROM PLUGINS ORDER BY ID ASC
This will give you a list of the current plugins you have. If you want to know more try this query:
SELECT ID,VERSION,NAME,TYPE FROM PLUGINS ORDER BY ID ASC, VERSION DESC
The second query will show if you have multiple versions. The system should pick the highest numbered version, but I do not trust that. IMHO, always keep just the latest copy of each plugin.
The second thing to do is to make the plugin utility easier to use. Here's how: Open the ant.properties file and make sure you have filled in the provided values. I use MW_HOME in these examples but they need to be your $MW_HOME, spelled out in the file.
wls.home=$MW_HOME/wlserver_10.3
oim.home=$MW_HOME/Oracle_IDM1/server
login.config=${oim.home}/config/authwl.conf
mw.home=$MW_HOME
Correction: ant does not pick up the environment variables
mw.home=/u01/app/oracle/fmw
wls.home=/u01/app/oracle/fmw/wlserver_10.3
oim.home=/u01/app/oracle/fmw/Oracle_IDM1/server
Third, add the next 3 lines to the same file:
OIM.Username=xelsysadm
OIM.UserPassword=<your password>
ServerURL=t3://yourservice.yoursystem.yourdomain:14000
CtxFactory=weblogic.jndi.WLInitialContextFactory
Then you just run ant -f pluginregistration.xml unregister
All you have to type in is the password for xelsysadm
and paste the full class name from the export you did in step 1.
For the file names when you are running ant -f pluginregistration.xml register
I copy the files into a /home/oracle/plugins folder and then use:
find ~/plugins -name '*plugin*' -print
And then copy the line with the full pathname before I run the ant script. Again I just enter the password for xelsysadm and then paste the filename.
Be sure to fully stop and restart all servers (no rolling restarts) to make the new plugins active. I have found that PurgeCache does not work.
SELECT DISTINCT(ID) FROM PLUGINS ORDER BY ID ASC
This will give you a list of the current plugins you have. If you want to know more try this query:
SELECT ID,VERSION,NAME,TYPE FROM PLUGINS ORDER BY ID ASC, VERSION DESC
The second query will show if you have multiple versions. The system should pick the highest numbered version, but I do not trust that. IMHO, always keep just the latest copy of each plugin.
The second thing to do is to make the plugin utility easier to use. Here's how: Open the ant.properties file and make sure you have filled in the provided values. I use MW_HOME in these examples but they need to be your $MW_HOME, spelled out in the file.
login.config=${oim.home}/config/authwl.conf
Correction: ant does not pick up the environment variables
mw.home=/u01/app/oracle/fmw
wls.home=/u01/app/oracle/fmw/wlserver_10.3
oim.home=/u01/app/oracle/fmw/Oracle_IDM1/server
Third, add the next 3 lines to the same file:
OIM.Username=xelsysadm
OIM.UserPassword=<your password>
ServerURL=t3://yourservice.yoursystem.yourdomain:14000
CtxFactory=weblogic.jndi.WLInitialContextFactory
Then you just run ant -f pluginregistration.xml unregister
All you have to type in is the password for xelsysadm
and paste the full class name from the export you did in step 1.
For the file names when you are running ant -f pluginregistration.xml register
I copy the files into a /home/oracle/plugins folder and then use:
find ~/plugins -name '*plugin*' -print
And then copy the line with the full pathname before I run the ant script. Again I just enter the password for xelsysadm and then paste the filename.
Be sure to fully stop and restart all servers (no rolling restarts) to make the new plugins active. I have found that PurgeCache does not work.
Tuesday, February 18, 2014
OIM11gR2 Using the old Thor interfaces
Sometimes you need to use the old Thor interfaces for getting information from the system. Lookups are one of these items, and that will be the example used here.
Also see my other posting OIM How to pull an IT Resource Parameter
Import the resource:
import Thor.API.Operations.tcLookupOperationsIntf;
Define the interface (spell something differently, in this case I used lower case L in lookup):
tcLookupOperationsIntf tclookupOperationsIntf =null;
Get the service:
tclookupOperationsintf = Platform.getService(tcLookupOperationsIntf.class);
Optionally you can do this all in one line. You should null check the returned value.
Here's a completed task that just checks to see if a value is in a list:
Thor.API.tcResultSet rs=null;
try {
rs=tclookupOperationsIntf.getLookupValues(validAccountLookup);
int rowcount=rs.getRowCount();
for (int irow=0; irow < rowcount; ++irow) {
rs.goToRow(irow);
String codeKey=rs.getStringValue
("Lookup Definition.Lookup Code Information.Code Key");
String decode=rs.getStringValue
("Lookup Definition.Lookup Code Information.Decode");
if (appInstanceName.equals(codeKey)) {
logger.logp(Level.FINE, getClass().getName(), methodName,
"Found "+appInstanceName+" in row "+irow+", returning true");
return true;
}
}
}
I left out all of the checks and catches, just showing functional code.
Also see my other posting OIM How to pull an IT Resource Parameter
Import the resource:
import Thor.API.Operations.tcLookupOperationsIntf;
Define the interface (spell something differently, in this case I used lower case L in lookup):
tcLookupOperationsIntf tclookupOperationsIntf =null;
Get the service:
tclookupOperationsintf = Platform.getService(tcLookupOperationsIntf.class);
Optionally you can do this all in one line. You should null check the returned value.
Here's a completed task that just checks to see if a value is in a list:
Thor.API.tcResultSet rs=null;
try {
rs=tclookupOperationsIntf.getLookupValues(validAccountLookup);
int rowcount=rs.getRowCount();
for (int irow=0; irow < rowcount; ++irow) {
rs.goToRow(irow);
String codeKey=rs.getStringValue
("Lookup Definition.Lookup Code Information.Code Key");
String decode=rs.getStringValue
("Lookup Definition.Lookup Code Information.Decode");
if (appInstanceName.equals(codeKey)) {
logger.logp(Level.FINE, getClass().getName(), methodName,
"Found "+appInstanceName+" in row "+irow+", returning true");
return true;
}
}
}
I left out all of the checks and catches, just showing functional code.
Friday, January 17, 2014
Oracle OIM11gR2 finding the uploaded jar files
Thanks again to my colleagues for pointing this out.
The jar files you uploaded through UploadJars.sh are contained in the OIMHOME_JARS table. It doesn't appear to use the update date so you will need to download the BLOB and SHA1 it to see if it is exactly what you expected to see.
Here's a hint. Don't use a version numbered file for Java Tasks jar files. You basically have to maintain that version number forever. Better to use the non-version numbered jar file for deployment and use SHA1 to check a version numbered copy against what you have deployed.
Update: you can use a version numbered jar file for Java Tasks jar files. The only issue is that you will see references to the older versions in the task adapters and you may be confused. It is not an issue and the class loader will go to the new jar file.
The jar files you uploaded through UploadJars.sh are contained in the OIMHOME_JARS table. It doesn't appear to use the update date so you will need to download the BLOB and SHA1 it to see if it is exactly what you expected to see.
Here's a hint. Don't use a version numbered file for Java Tasks jar files. You basically have to maintain that version number forever. Better to use the non-version numbered jar file for deployment and use SHA1 to check a version numbered copy against what you have deployed.
Update: you can use a version numbered jar file for Java Tasks jar files. The only issue is that you will see references to the older versions in the task adapters and you may be confused. It is not an issue and the class loader will go to the new jar file.
Thursday, October 24, 2013
SSL Keytool Mojo
Keytool setup: put the following into your .bash_profile:
JAVA_KEYSTORE="-keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit"
DEMOTRUST_KEYSTORE="-keystore $WL_HOME/server/lib/DemoTrust.jks -storepass DemoTrustKeyStorePassPhrase"
This will make it easy to use keytool. Then you can do:
keytool -list $JAVA_KEYSTORE
keytool -list $JAVA_KEYSTORE | grep rootca
keytool -delete -alias rootca $JAVA_KEYSTORE
keytool -import -alias rootca -file <filename> $JAVA_KEYSTORE
JAVA_KEYSTORE="-keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit"
DEMOTRUST_KEYSTORE="-keystore $WL_HOME/server/lib/DemoTrust.jks -storepass DemoTrustKeyStorePassPhrase"
This will make it easy to use keytool. Then you can do:
keytool -list $JAVA_KEYSTORE
keytool -list $JAVA_KEYSTORE | grep rootca
keytool -delete -alias rootca $JAVA_KEYSTORE
keytool -import -alias rootca -file <filename> $JAVA_KEYSTORE
Subscribe to:
Posts (Atom)