Last active
December 1, 2015 18:02
-
-
Save emrekgn/70444bd58c79c19ddc4f to your computer and use it in GitHub Desktop.
sources.list URL Parser - Prints out packages defined by repository URL
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package tr.org.sources.list.parser; | |
import java.io.BufferedReader; | |
import java.io.IOException; | |
import java.io.InputStreamReader; | |
import java.io.Serializable; | |
import java.lang.reflect.Method; | |
import java.util.HashSet; | |
import java.util.Set; | |
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream; | |
import org.apache.http.HttpEntity; | |
import org.apache.http.HttpResponse; | |
import org.apache.http.client.ClientProtocolException; | |
import org.apache.http.client.HttpClient; | |
import org.apache.http.client.methods.HttpGet; | |
import org.apache.http.impl.client.HttpClientBuilder; | |
/** | |
* A utility class which is responsible for parsing specified Linux package | |
* repository URL and returning a set of packages.<br/> | |
* <br/> | |
* | |
* Repository format for a sample sources.list is explained below:<br/> | |
* | |
* deb http://ch.archive.ubuntu.com/ubuntu/ saucy main restricted<br/> | |
* deb-src http://ch.archive.ubuntu.com/ubuntu/ saucy main restricted<br/> | |
* <br/> | |
* | |
* <b>deb:</b> These repositories contain binaries or precompiled packages. | |
* These repositories are required for most users.<br/> | |
* <b>deb-src:</b> These repositories contain the source code of the packages. | |
* Useful for developers.<br/> | |
* <b>http://ch.archive.ubuntu.com/ubuntu/:</b> The URI (Uniform Resource | |
* Identifier), in this case a location on the internet.<br/> | |
* <b>saucy:</b> is the release name of your <b>distribution</b>.<br/> | |
* <b>main & restricted:</b> are the section names or components. There can be | |
* <b>several component names</b>, separated by spaces.<br/> | |
* <br/> | |
* | |
* Please visit https://help.ubuntu.com/community/Repositories/CommandLine for | |
* more information. | |
* | |
*/ | |
public class RepoSourcesListParser { | |
/** | |
* Parses repository URL and returns a set of PackageInfo | |
* | |
* @param url | |
* @param distribution | |
* @param components | |
* @param architecture | |
* @return | |
*/ | |
public Set<PackageInfo> parseURL(String url, String distribution, | |
String[] components, String architecture) { | |
Set<PackageInfo> packages = new HashSet<PackageInfo>(); | |
for (String component : components) { | |
try { | |
// Find URL pointing to the package file | |
String packageURL = findPackageURL(url, distribution, | |
component, architecture); | |
System.out.println("URL: " + packageURL); | |
// GET package file | |
HttpClient client = HttpClientBuilder.create().build(); | |
HttpGet request = new HttpGet(packageURL); | |
HttpResponse response = client.execute(request); | |
System.out.println("Response code: " | |
+ response.getStatusLine().getStatusCode()); | |
HttpEntity entity = response.getEntity(); | |
if (entity != null) { | |
// Extract package file | |
BZip2CompressorInputStream inputStream = new BZip2CompressorInputStream( | |
entity.getContent()); | |
if (inputStream != null) { | |
BufferedReader reader = new BufferedReader( | |
new InputStreamReader(inputStream)); | |
if (reader != null) { | |
String line = ""; | |
PackageInfo info = null; | |
while ((line = reader.readLine()) != null) { | |
// Empty line means new package! | |
if (info == null || line.trim().isEmpty()) { | |
info = new PackageInfo(); | |
packages.add(info); | |
} | |
if (line.trim().isEmpty()) { | |
continue; | |
} | |
String[] tokens = line.split(":", 2); | |
String propertyMethodName = getPropertyMethodName(tokens[0] | |
.trim()); | |
String propertyValue = tokens[1].trim(); | |
setPropertyValue(info, propertyMethodName, | |
propertyValue); | |
} | |
} | |
reader.close(); | |
} | |
} | |
} catch (ClientProtocolException e) { | |
e.printStackTrace(); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
} | |
return packages; | |
} | |
/** | |
* Finds the package URL (Packages.bz2) in the specified repository URL | |
* | |
* @param url | |
* @param distribution | |
* @param component | |
* @param architecture | |
* @return | |
*/ | |
private String findPackageURL(String url, String distribution, | |
String component, String architecture) { | |
String packageURL = url; | |
if (!url.endsWith("/")) { | |
packageURL += "/"; | |
} | |
packageURL += "dists/"; | |
packageURL += distribution + "/"; | |
packageURL += component + "/"; | |
packageURL += "binary-" + architecture + "/Packages.bz2"; | |
return packageURL; | |
} | |
private String getPropertyMethodName(String propertyName) { | |
// To avoid violation of java variable declaration, use 'packageName' | |
// instead of 'package' | |
if ("package".equalsIgnoreCase(propertyName)) { | |
return "setPackageName"; | |
} | |
final StringBuilder nameBuilder = new StringBuilder("set"); | |
boolean capitalizeNextChar = true; | |
boolean first = true; | |
for (int i = 0; i < propertyName.length(); i++) { | |
final char c = propertyName.charAt(i); | |
if (!Character.isLetterOrDigit(c)) { | |
if (!first) { | |
capitalizeNextChar = true; | |
} | |
} else { | |
nameBuilder.append(capitalizeNextChar ? Character | |
.toUpperCase(c) : Character.toLowerCase(c)); | |
capitalizeNextChar = Character.isDigit(c); | |
first = false; | |
} | |
} | |
return nameBuilder.toString(); | |
} | |
private void setPropertyValue(PackageInfo info, String propertyMethodName, | |
String propertyValue) { | |
Method method = null; | |
try { | |
method = info.getClass() | |
.getMethod(propertyMethodName, String.class); | |
if (method != null) { | |
method.invoke(info, propertyValue); | |
} | |
} catch (Exception e) { | |
// Leaving catch block empty is almost always a bad practice but | |
// PackageInfo class does not have all the properties so we'll just | |
// ignore NoSuchMethodException here | |
} | |
} | |
/** | |
* A modal class to contain all the info about a package | |
* | |
*/ | |
public class PackageInfo implements Serializable { | |
private static final long serialVersionUID = 5165756804600495682L; | |
private String packageName; | |
private String priority; | |
private String section; | |
private String installedSize; | |
private String maintainer; | |
private String architecture; | |
private String source; | |
private String version; | |
private String depends; | |
private String recommends; | |
private String breaks; | |
private String filename; | |
private String size; | |
private String md5Sum; | |
private String sha1; | |
private String sha256; | |
private String description; | |
private String tag; | |
private String descriptionMd5; | |
private String homepage; | |
private String conflicts; | |
private String suggests; | |
private String multiArch; | |
private String replaces; | |
private String provides; | |
private String preDepends; | |
public String getPackageName() { | |
return packageName; | |
} | |
public void setPackageName(String packageName) { | |
this.packageName = packageName; | |
} | |
public String getPriority() { | |
return priority; | |
} | |
public void setPriority(String priority) { | |
this.priority = priority; | |
} | |
public String getSection() { | |
return section; | |
} | |
public void setSection(String section) { | |
this.section = section; | |
} | |
public String getInstalledSize() { | |
return installedSize; | |
} | |
public void setInstalledSize(String installedSize) { | |
this.installedSize = installedSize; | |
} | |
public String getMaintainer() { | |
return maintainer; | |
} | |
public void setMaintainer(String maintainer) { | |
this.maintainer = maintainer; | |
} | |
public String getArchitecture() { | |
return architecture; | |
} | |
public void setArchitecture(String architecture) { | |
this.architecture = architecture; | |
} | |
public String getSource() { | |
return source; | |
} | |
public void setSource(String source) { | |
this.source = source; | |
} | |
public String getVersion() { | |
return version; | |
} | |
public void setVersion(String version) { | |
this.version = version; | |
} | |
public String getDepends() { | |
return depends; | |
} | |
public void setDepends(String depends) { | |
this.depends = depends; | |
} | |
public String getRecommends() { | |
return recommends; | |
} | |
public void setRecommends(String recommends) { | |
this.recommends = recommends; | |
} | |
public String getBreaks() { | |
return breaks; | |
} | |
public void setBreaks(String breaks) { | |
this.breaks = breaks; | |
} | |
public String getFilename() { | |
return filename; | |
} | |
public void setFilename(String filename) { | |
this.filename = filename; | |
} | |
public String getSize() { | |
return size; | |
} | |
public void setSize(String size) { | |
this.size = size; | |
} | |
public String getMd5Sum() { | |
return md5Sum; | |
} | |
public void setMd5Sum(String md5Sum) { | |
this.md5Sum = md5Sum; | |
} | |
public String getSha1() { | |
return sha1; | |
} | |
public void setSha1(String sha1) { | |
this.sha1 = sha1; | |
} | |
public String getSha256() { | |
return sha256; | |
} | |
public void setSha256(String sha256) { | |
this.sha256 = sha256; | |
} | |
public String getDescription() { | |
return description; | |
} | |
public void setDescription(String description) { | |
this.description = description; | |
} | |
public String getTag() { | |
return tag; | |
} | |
public void setTag(String tag) { | |
this.tag = tag; | |
} | |
public String getDescriptionMd5() { | |
return descriptionMd5; | |
} | |
public void setDescriptionMd5(String descriptionMd5) { | |
this.descriptionMd5 = descriptionMd5; | |
} | |
public String getHomepage() { | |
return homepage; | |
} | |
public void setHomepage(String homepage) { | |
this.homepage = homepage; | |
} | |
public String getConflicts() { | |
return conflicts; | |
} | |
public void setConflicts(String conflicts) { | |
this.conflicts = conflicts; | |
} | |
public String getSuggests() { | |
return suggests; | |
} | |
public void setSuggests(String suggests) { | |
this.suggests = suggests; | |
} | |
public String getMultiArch() { | |
return multiArch; | |
} | |
public void setMultiArch(String multiArch) { | |
this.multiArch = multiArch; | |
} | |
public String getReplaces() { | |
return replaces; | |
} | |
public void setReplaces(String replaces) { | |
this.replaces = replaces; | |
} | |
public String getProvides() { | |
return provides; | |
} | |
public void setProvides(String provides) { | |
this.provides = provides; | |
} | |
public String getPreDepends() { | |
return preDepends; | |
} | |
public void setPreDepends(String preDepends) { | |
this.preDepends = preDepends; | |
} | |
@Override | |
public String toString() { | |
return "Package: " + packageName + " " + version; | |
} | |
} | |
public static void main(String[] args) { | |
RepoSourcesListParser parser = new RepoSourcesListParser(); | |
Set<PackageInfo> packages; | |
// Example 1: | |
packages = parser.parseURL("http://security.debian.org", | |
"wheezy/updates", new String[] { "main" }, "amd64"); | |
for (PackageInfo pkg : packages) { | |
System.out.println(pkg.toString()); | |
} | |
// Example 2: | |
packages = parser.parseURL("http://tr.archive.ubuntu.com/ubuntu", | |
"vivid", new String[] { "main" }, "amd64"); | |
for (PackageInfo pkg : packages) { | |
System.out.println(pkg.toString()); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment