Yesterday I had to write a piece of code that would install maven dependencies onto the local computer of the user. This is pretty easy with a line of bash code, but when you have to move 700 or so...having a program do it for you would be much easier.
I had never previously used Java to access the system prompts of a computer, so this was all new to me. So how did I do it?
I had never previously used Java to access the system prompts of a computer, so this was all new to me. So how did I do it?
- Tell the computer the location of the directory that you want to move files from.
- Check that that directory exists.
- Repeat this recursively until the you reach the end (ie. find a file and not a folder).
- When you find the file you will want to play about with it to get the correct form to pass out to the system as bash code.
Below are the steps that I required to get this to work. I know that it is bad practice to stick everything in one class, but for the purposes of this task I was required to.
Create a new java project in Eclipse (or IDE of your choice)
Create a new public java class "JarExtractor" (you can name this whatever you like, but remember to change it throughout this tutorial).
Make a main method within the class JarExtractor.
public static void main(String[] args) {
}
Instantiate an instance of 'JarExtractor' within the main method. And start up threads (this will speed up the process.)
JarExtractor extractor = new JarExtractor(); ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(5);
executor.setMaximumPoolSize(5);
The line of bash code that is used to move a file is:mvn install:install-file - DgroupId=javax.transaction -DartifactId=jta -Dpackaging=jar -Dversion=1.0.1B -Dfile=jta-1.0.1B.jar
so you have a GroupID, an ArtifactID, a Packaging, a Version and the File name itself. To handle this I built a private class called 'MavenObject' and populated it with these variables (I didn't include packaging as for the purposes of this task, I am going to assume that all files are .jar).
The class for MavenObject looks like this:
private class MavenObject {
private String artifactID;
private String groupID;
private String version;
private String pathToJar;
public MavenObject(String artifactID, String groupID, String version,
String pathToJar) {
super();
this.artifactID = artifactID;
this.groupID = groupID;
this.version = version;
this.pathToJar = pathToJar;
}
// All getters
}
Now we have the class to handle the objects, we have to create a HashMap (in the main method) that will handle this:
HashMap<String, MavenObject> jarMap = new HashMap<String, MavenObject>();
This map will hold a key to each of the jars that the recursive search finds.
Search for the jars:
extractor.findJar(new File(aseRepo), jarMap);
This is a call to another method called 'findJar'. This method is recursive and iterates through all the folders in the directories to find all the files. Below is the code that is used to do this.
public void findJar(File file, HashMap<String, MavenObject> jarMap) {
if (file.isDirectory()) {
for (File i : file.listFiles()) {
findJar(i, jarMap);
}
} else if (file.isFile()) {
MavenObject mvnObj = extractMavenObject(file);
if (mvnObj != null) {
jarMap.put(file.getName(), mvnObj);
}
} else {
System.out.println("Something Weird has happened");
}
}
This method checks several things:
- Is the item it is currently at a folder? Enter and repeat until reach a file.
- Is the item a file? Get the required details about it and put in the map.
- If there is nothing currently in the map for that file, add it to the map.
- If it's not a folder and it's not a file then something is horribly wrong.
Extracting the information we need to populate a Maven Object. This is all done in another method 'extractMavenObject'. To allow us to extract the information we need, we need to pass the file through as a parameter.
private MavenObject extractMavenObject(File file) {
// Get the file name (ie. qwerty_1_1_release.jar)
String name = file.getName();
// Check that the file is a JAR file
if (file.getName().endsWith(".jar")) {
// Get the path to the JAR (this will be used to get groupId, artifactId etc.)
String pathToJar = file.getAbsolutePath();
String path = pathToJar.replace("BASE_DIRECTORY_NAME", "");
// Split the string where a '/' is present. This will help you access the version and artifactId.
String[] pathArray = path.split("/");
int length = pathArray.length;
String version = pathArray[length - 2]; //The version of the JAR
String artifactID = pathArray[length - 3]; // The artifactID
// The group ID has to be got in order and with the '/' changed to '.'
String groupID = "";
for (int i = 0; i < length - 3; i++) {
groupID += pathArray[i] + ".";
}
// Remove the trailing '.'
groupID = groupID.substring(0, groupID.length() - 1);
return new MavenObject(artifactID, groupID, version, pathToJar);
} else {
System.err.print("The file: " + name + " is not a JAR");
return null;
}
}
That is all the main code handled. Now just have to access the system and send out the command and actually run the program. At this point we are passed back the the main method, with out now populated map of JAR files. It may be interesting at this point to see how many JARs there are. You can simple create a variable to get the size of the map.
int totalJars = jarMap.size();
Now we want to execute the command.
for (Entry<String, MavenObject> i : jarMap.entrySet()) {
try {
executor.execute(new InstallToLocalRepository(i.getKey(), i.getValue()));
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
So basically what this does is for each entry that there is in the map it will execute the command for that key and corresponding object. This is where the bash command I mentioned earlier comes into play:
private static class InstallToLocalRepository implements Runnable {
private MavenObject mavenObject;
String jarName;
private String mvnCMD = "mvn install:install-file -Dfile={path} -DgroupId={groupId} -DartifactId= {artifactId} -Dversion={version} -Dpackaging=jar";
public InstallToLocalRepository(String jarName, MavenObject mavenObject) {
super();
this.mavenObject = mavenObject;
this.jarName = jarName;
}
@Override
public void run() {
mvnCMD = mvnCMD.replace("{groupId}", mavenObject.getGroupID());
mvnCMD = mvnCMD.replace("{artifactId}", mavenObject.getArtifactID());
mvnCMD = mvnCMD.replace("{version}", mavenObject.getVersion());
mvnCMD = mvnCMD.replace("{path}", mavenObject.getPathToJar());
try {
Process p = Runtime.getRuntime().exec(mvnCMD);
String line;
BufferedReader br = new BufferedReader(new InputStreamReader(p.getErrorStream()));
while ((line = br.readLine()) != null) {
System.err.println(line);
}
System.out.println("[" + completed.incrementAndGet() + " of " + totalJars + "] Installed " + jarName);
} catch (Exception e) {
System.err.println("[" + completed.incrementAndGet() + " of " + totalJars + "] Failed to install " + jarName);
System.err.println(e.getStackTrace());
}
}
}
Finally add the following code to the main method:
while (!executor.isShutdown()) {
if (executor.getActiveCount() < 1) {
executor.shutdown();
}
}