Skip to content

Instantly share code, notes, and snippets.

@emrekgn
Last active December 1, 2015 18:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save emrekgn/70444bd58c79c19ddc4f to your computer and use it in GitHub Desktop.
Save emrekgn/70444bd58c79c19ddc4f to your computer and use it in GitHub Desktop.
sources.list URL Parser - Prints out packages defined by repository URL
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