/**
* Copyright (c) 2013/2014 Verein zur Foerderung der IT-Sicherheit in Oesterreich (SBA).
* The work has been developed in the TIMBUS Project and the above-mentioned are Members of the TIMBUS Consortium.
* TIMBUS is supported by the European Union under the 7th Framework Programme for research and technological
* development and demonstration activities (FP7/2007-2013) under grant agreement no. 269940.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including without
* limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTIBITLY, or FITNESS FOR A PARTICULAR
* PURPOSE. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise,
* unless required by applicable law or agreed to in writing, shall any Contributor be liable for damages, including
* any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this
* License or out of the use or inability to use the Work.
* See the License for the specific language governing permissions and limitation under the License.
*/
package net.timbusproject.dpes.alternative.kb;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import org.apache.commons.cli.BasicParser;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DurationFormatUtils;
import org.semanticweb.owlapi.apibinding.OWLManager;
import org.semanticweb.owlapi.io.FileDocumentTarget;
import org.semanticweb.owlapi.io.OWLXMLOntologyFormat;
import org.semanticweb.owlapi.io.RDFXMLOntologyFormat;
import org.semanticweb.owlapi.model.AddImport;
import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLClassExpression;
import org.semanticweb.owlapi.model.OWLDataFactory;
import org.semanticweb.owlapi.model.OWLDataProperty;
import org.semanticweb.owlapi.model.OWLNamedIndividual;
import org.semanticweb.owlapi.model.OWLObjectProperty;
import org.semanticweb.owlapi.model.OWLOntologyCreationException;
import org.semanticweb.owlapi.model.OWLOntologyFormat;
import org.semanticweb.owlapi.model.OWLOntologyID;
import org.semanticweb.owlapi.model.OWLOntologyManager;
import org.semanticweb.owlapi.model.OWLOntologyStorageException;
import uk.ac.manchester.cs.owl.owlapi.OWLObjectHasValueImpl;
import uk.ac.manchester.cs.owl.owlapi.OWLObjectIntersectionOfImpl;
import uk.ac.manchester.cs.owl.owlapi.OWLObjectUnionOfImpl;
import uk.ac.manchester.cs.owl.owlapi.OWLOntologyImpl;
/**
* @author Rudolf Mayer
*/
public class PackageUniverseBuilder {
public static final String IRIPREFIX_PACKAGE_UNIVERSE = "http://timbus.teco.edu/ontologies/preservationIdentifier/PackageUniverse";
public static final IRI IRI_CUDF_VERSIONEDPACKAGE = IRI.create(VirtualPackageAlternativeIdentifier.IRI_CUDF.toString()
+ "#VersionedPackage");
public static final OWLClass CLASS_CUDF_VERSIONEDPACKAGE = OWLManager.getOWLDataFactory().getOWLClass(
IRI_CUDF_VERSIONEDPACKAGE);
// Object Properties
public static final OWLObjectProperty OBJECTPROPERTY_CUDF_DEPENDS = OWLManager.getOWLDataFactory().getOWLObjectProperty(
IRI.create(VirtualPackageAlternativeIdentifier.IRI_CUDF.toString() + "#", "hasDependency"));
public static final OWLObjectProperty OBJECTPROPERTY_CUDF_CONFLICTS = OWLManager.getOWLDataFactory().getOWLObjectProperty(
IRI.create(VirtualPackageAlternativeIdentifier.IRI_CUDF.toString() + "#", "hasConflict"));
public static final OWLObjectProperty OBJECTPROPERTY_CUDF_RECOMMENDS = OWLManager.getOWLDataFactory().getOWLObjectProperty(
IRI.create(VirtualPackageAlternativeIdentifier.IRI_CUDF.toString() + "#", "hasRecommendation"));
public static final OWLObjectProperty OBJECTROPERTY_REALIZED_BY = OWLManager.getOWLDataFactory().getOWLObjectProperty(
IRI.create(VirtualPackageAlternativeIdentifier.IRI_CUDF.toString() + "#", "realizedBy"));
// Data Properties
public static final OWLDataProperty DATAPROPERTY_HAS_VERSION = OWLManager.getOWLDataFactory().getOWLDataProperty(
IRI.create(VirtualPackageAlternativeIdentifier.IRI_CUDF.toString() + "#", "hasVersion"));
public static final OWLDataProperty DATAPROPERTY_HAS_NAME = OWLManager.getOWLDataFactory().getOWLDataProperty(
IRI.create(VirtualPackageAlternativeIdentifier.IRI_CUDF.toString() + "#", "hasName"));
public static final OWLDataProperty DATAPROPERTY_HAS_COMPARATOR = OWLManager.getOWLDataFactory().getOWLDataProperty(
IRI.create(VirtualPackageAlternativeIdentifier.IRI_CUDF.toString() + "#", "hasComparator"));
public static final String aptitudeSearchCommand = "aptitude search -F %p \".*\"";
static final Logger logUniverse = Logger.getLogger("PackaUniverseBuilder");
public static void main(String[] args) throws IOException, ClassNotFoundException {
// this holds all the packages
SortedMap<String, Package> allPackages = new TreeMap<String, Package>();
Options options = new Options();
options.addOption(new Option("l", "loadPackages", true, "Load package information from a serialised file"));
options.addOption(new Option("x", "loadPackagesXML", true,
"Load package information from an XML serialised file"));
options.addOption(new Option("j", "loadPackagesJSON", true,
"Load package information from a JSON serialised file"));
CommandLineParser parser = new BasicParser();
try {
CommandLine cmd = parser.parse(options, args);
if (cmd.hasOption("loadPackages")) { // load the package information from the serialised file
String providersFileName = cmd.getOptionValue("loadPackages");
logUniverse.info("Trying to load package information from Binary " + providersFileName);
allPackages = (SortedMap<String, Package>) new ObjectInputStream(new FileInputStream(providersFileName)).readObject();
logUniverse.info("\tDone, found " + allPackages.size() + " packages.");
}
if (cmd.hasOption("loadPackagesXML")) { // load the package information from the XML file
String providersFileName = cmd.getOptionValue("loadPackagesXML");
logUniverse.info("Trying to load package information from XML " + providersFileName);
allPackages = (SortedMap<String, Package>) SerialisationUtils.readFromXMLFile(providersFileName);
logUniverse.info("\tDone, found " + allPackages.size() + " packages.");
}
if (cmd.hasOption("loadPackagesJSON")) { // load the package information from the XML file
String providersFileName = cmd.getOptionValue("loadPackagesJSON");
logUniverse.info("Trying to load package information from JSON " + providersFileName);
allPackages = (SortedMap<String, Package>) SerialisationUtils.readFromJSONFile(providersFileName);
logUniverse.info("\tDone, found " + allPackages.size() + " packages.");
}
} catch (ParseException e) {
System.err.println("CLI parsing failed. Reason: " + e.getMessage());
// automatically generate the help statement
HelpFormatter formatter = new HelpFormatter();
formatter.printHelp("ant", options);
return;
}
long startTime = System.currentTimeMillis();
List<Future<Package>> futuresList = queryNotLoadedPackages(allPackages);
// store the results - if there were any
if (futuresList.size() > 0) {
long endReadingPackagesTime = System.currentTimeMillis();
logUniverse.info("Reading packages took "
+ DurationFormatUtils.formatDurationHMS(endReadingPackagesTime - startTime));
for (Future<Package> future : futuresList) {
Package pkg;
try {
pkg = future.get();
allPackages.put(pkg.getName(), pkg);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
// save results
final String fileName = "packageDetails-" + OSIdentifier.getEscapedOSString();
// object serialisation
logUniverse.info("Wrote packages to "
+ SerialisationUtils.writeAsBinary(allPackages,
VirtualPackageAlternativeIdentifier.PATH_KNOWDLEDGE_BASE + fileName).getAbsolutePath());
// save packages as JSON
try {
logUniverse.info("Wrote packages to "
+ SerialisationUtils.writeAsJSON(allPackages,
VirtualPackageAlternativeIdentifier.PATH_KNOWDLEDGE_BASE, fileName, true).getAbsolutePath());
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
// save packages in XML
try {
logUniverse.info("Wrote packages to "
+ SerialisationUtils.writeAsXML(allPackages,
VirtualPackageAlternativeIdentifier.PATH_KNOWDLEDGE_BASE, fileName, true).getAbsolutePath());
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
}
// process all packages
for (Package pkg : allPackages.values()) {
// process the lines
for (String str : pkg.getPackageInformation()) {
if (str.trim().length() == 0) {
continue;
}
str = str.trim();
int keyValueSeparator = str.indexOf(":");
if (keyValueSeparator == -1) {
System.out.println("Skipping wrong str: " + str);
continue;
}
// String[] parts = str.split(":");
String key = str.substring(0, keyValueSeparator);
String value = str.substring(keyValueSeparator + 1).trim();
if (key.equals("Package")) {
pkg.setName(value);
} else if (key.equals("Depends")) {
pkg.setDependsString(value);
} else if (key.equals("Conflicts")) {
pkg.setConflictsString(value);
} else if (key.equals("Recommends")) {
pkg.setRecommendsString(value);
} else if (key.equals("Version")) {
pkg.setVersionString(value);
}
}
if (allPackages.size() == 10) {
break;
}
}
logUniverse.info("Pre-parsed all packages");
final String ontologyPrefix = "packageUniverse-" + OSIdentifier.getEscapedOSString();
OWLOntologyImpl ontology = convertToOWL(allPackages, ontologyPrefix);
logUniverse.info("Converted to OWL");
File file = new File(VirtualPackageAlternativeIdentifier.PATH_KNOWDLEDGE_BASE + ontologyPrefix + ".owl");
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
logUniverse.info("Created directory " + file.getParentFile().getAbsolutePath());
}
FileDocumentTarget fileDocumentTarget = new FileDocumentTarget(file);
try {
OWLOntologyFormat format = new RDFXMLOntologyFormat();
format = new OWLXMLOntologyFormat();
OWLManager.createOWLOntologyManager().saveOntology(ontology, format, fileDocumentTarget);
logUniverse.info("Saved to " + file.getAbsolutePath());
} catch (OWLOntologyStorageException e) {
e.printStackTrace();
}
long totalEndTime = System.currentTimeMillis();
logUniverse.info("Total duration: " + DurationFormatUtils.formatDurationHMS(totalEndTime - startTime));
logUniverse.info("Trying to load ontology again from " + file.getAbsolutePath());
try {
OWLManager.createOWLOntologyManager().loadOntologyFromOntologyDocument(file);
logUniverse.info("... Success");
} catch (OWLOntologyCreationException e) {
e.printStackTrace();
}
}
public static List<Future<Package>> queryNotLoadedPackages(SortedMap<String, Package> allPackages) {
// search all packages
ArrayList<String> allPackageNames = VirtualPackageAlternativeIdentifier.searchPackages(aptitudeSearchCommand);
logUniverse.info("Found " + allPackageNames.size() + " packages.\n");
// read missing packages
// query the package information, in parallel manner
int nrOfProcessors = Runtime.getRuntime().availableProcessors();
ExecutorService eservice = Executors.newFixedThreadPool(nrOfProcessors);
logUniverse.info("*** Working with " + nrOfProcessors + " parallel processes");
List<Future<Package>> futuresList = new ArrayList<Future<Package>>();
int maxTestCount = 50;
int index = 0;
for (String packageName : allPackageNames) {
index++;
// check if we need to query this package
if (allPackages.containsKey(packageName)) {
// logUniverse.info("Not querying already loaded package " + packageName);
} else {
futuresList.add(eservice.submit(new PackgeDetailsTask(packageName)));
}
// if (index == maxTestCount) {
// break;
// }
}
// wait for all tasks to finish
eservice.shutdown();
try {
eservice.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
System.out.println(e);
}
return futuresList;
}
public static OWLOntologyImpl convertToOWL(SortedMap<String, Package> allPackages, String ontologyPrefix) {
OWLDataFactory df = OWLManager.getOWLDataFactory();
OWLOntologyManager manager = OWLManager.createOWLOntologyManager(df);
IRI ontologyIRI = IRI.create(IRIPREFIX_PACKAGE_UNIVERSE + ontologyPrefix + ".owl");
OWLOntologyImpl ontology = new OWLOntologyImpl(manager, new OWLOntologyID(ontologyIRI));
manager.applyChange(new AddImport(ontology,
df.getOWLImportsDeclaration(VirtualPackageAlternativeIdentifier.IRI_CUDF)));
// 1. create the packages
HashMap<Package, OWLNamedIndividual> indivMap = new HashMap<Package, OWLNamedIndividual>();
for (Entry<String, Package> entry : allPackages.entrySet()) {
// 1. I.) individual creation & create class assertion (CUDF#Package)
OWLNamedIndividual packageIndiv = OWLUtils.createAndRegisterIndividual(ontologyIRI.toString(),
entry.getKey(), VirtualPackageAlternativeIdentifier.CLASS_CUDF_PACKAGE, df, manager, ontology);
Package pkg = entry.getValue();
indivMap.put(pkg, packageIndiv);
OWLUtils.addDataProperty(packageIndiv, ontology, df, manager, DATAPROPERTY_HAS_VERSION, pkg.getName());
if (StringUtils.isNotBlank(pkg.getVersionString())) {
OWLUtils.addDataProperty(packageIndiv, ontology, df, manager, DATAPROPERTY_HAS_VERSION,
pkg.getVersionString());
}
}
final TreeSet<String> treeSet = new TreeSet<String>(allPackages.keySet());
try {
FileUtils.writeLines(new File("/tmp/allPackages.txt"), treeSet);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for (Entry<Package, OWLNamedIndividual> entry : indivMap.entrySet()) {
OWLNamedIndividual packageIndiv = entry.getValue();
// createRelations(df, manager, ontologyIRI, ontology, packageIndiv, entry.getKey().getDepends(),
// OBJECTPROPERTY_CUDF_DEPENDS);
// createRelations(df, manager, ontologyIRI, ontology, packageIndiv, entry.getKey().getConflicts(),
// OBJECTPROPERTY_CUDF_CONFLICTS);
// createRelations(df, manager, ontologyIRI, ontology, packageIndiv, entry.getKey().getRecommends(),
// OBJECTPROPERTY_CUDF_RECOMMENDS);
//
// // do post-processing ==> after all packages are read, we can resolve the links
// for (Package pkg : allPackages.values()) {
// pkg.resolveLinks(allPackages);
// }
parseDependencyPackages(packageIndiv, entry.getKey(), entry.getKey().getDependsString(), allPackages,
indivMap, df, manager, ontologyIRI, ontology, OBJECTPROPERTY_CUDF_DEPENDS);
}
logUniverse.info("Resolved links between packages");
return ontology;
}
public static void parseDependencyPackages(OWLNamedIndividual packageIndiv, Package pkg, String pkgListString,
Map<String, Package> packageNameMap, HashMap<Package, OWLNamedIndividual> indivMap, OWLDataFactory df,
OWLOntologyManager manager, IRI ontologyIRI, OWLOntologyImpl ontology, OWLObjectProperty property) {
ArrayList<OWLClassExpression> simpleAndDependencies = new ArrayList<OWLClassExpression>();
if (pkgListString != null) {
final String[] allReferences = pkgListString.split(",");
for (String referenceStr : allReferences) {
referenceStr = referenceStr.trim();
if (referenceStr.contains("|")) {
// parse each individual reference, combine them to union afterwards
HashSet<OWLClassExpression> orDependencies = new HashSet<OWLClassExpression>();
for (String reference : referenceStr.split("\\|")) {
reference = reference.trim();
OWLObjectHasValueImpl objectHasValueExpression = parseReference(packageIndiv, pkg, indivMap,
packageNameMap, df, manager, ontologyIRI, ontology, property, reference);
if (objectHasValueExpression == null) {
System.out.println("Did not find a reference for " + reference);
}
orDependencies.add(objectHasValueExpression);
}
// assemble union, add to other dependencies (TODO: or not? add it directly as simple union?)
OWLObjectUnionOfImpl union = new OWLObjectUnionOfImpl(orDependencies);
simpleAndDependencies.add(union);
// System.out.println("\t\tIgnoring package: " + parsedPackageInfo.getName() + "; ref was: " + packageRef);
} else {
OWLObjectHasValueImpl objectHasValueExpression = parseReference(packageIndiv, pkg, indivMap,
packageNameMap, df, manager, ontologyIRI, ontology, property, referenceStr);
simpleAndDependencies.add(objectHasValueExpression);
}
}
}
if (simpleAndDependencies.size() == 1) {
OWLUtils.assertClass(packageIndiv, simpleAndDependencies.get(0), ontology, df, manager);
} else if (simpleAndDependencies.size() > 1) {
OWLObjectIntersectionOfImpl intersection = new OWLObjectIntersectionOfImpl(new HashSet<OWLClassExpression>(
simpleAndDependencies));
OWLUtils.assertClass(packageIndiv, intersection, ontology, df, manager);
}
}
private static OWLObjectHasValueImpl parseReference(OWLNamedIndividual packageIndiv, Package pkg,
HashMap<Package, OWLNamedIndividual> indivMap, Map<String, Package> packageNameMap, OWLDataFactory df,
OWLOntologyManager manager, IRI ontologyIRI, OWLOntologyImpl ontology, OWLObjectProperty property,
String referenceStr) {
String targetPackageName;
String comparator = null;
String targetVersion = null;
// OWLNamedIndividual targetIndiv = getOrCreateTargetIndiv(packageNameMap, indivMap, df, manager,
// ontologyIRI, ontology, targetPackageName);
// OWLUtils.createRelation(packageIndiv, targetIndiv, ontology, df, manager, property);
boolean isReferenceWithVersion = referenceStr.contains("(") && referenceStr.contains(")");
if (!isReferenceWithVersion) { // simple package
targetPackageName = referenceStr.trim();
} else { // assume a versioned package relation
targetPackageName = referenceStr.substring(0, referenceStr.indexOf("(")).trim();
// parse info on referenced package
String[] referenceStrParts = referenceStr.split("\\(");
String pkgRelation = referenceStrParts[1].trim();
if (!pkgRelation.endsWith(")")) {
System.out.println("The package relation string details doesn't end with ) for " + pkgRelation);
return null;
}
pkgRelation = pkgRelation.substring(0, pkgRelation.length() - 1);
String[] pkgVersionDetailParts = pkgRelation.split(" ");
comparator = pkgVersionDetailParts[0].trim();
targetVersion = pkgVersionDetailParts[1].trim();
}
String versionedPackageName = pkg.getName() + targetPackageName;
// create reference individual, aka "VersionedPackage"
OWLNamedIndividual virtualPackageIndiv = OWLUtils.createAndRegisterIndividual(ontologyIRI.toString(),
versionedPackageName, CLASS_CUDF_VERSIONEDPACKAGE, df, manager, ontology);
if (StringUtils.isNotBlank(targetVersion)) {
OWLUtils.addDataProperty(virtualPackageIndiv, ontology, df, manager, DATAPROPERTY_HAS_VERSION,
targetVersion);
}
if (StringUtils.isNotBlank(comparator)) {
OWLUtils.addDataProperty(virtualPackageIndiv, ontology, df, manager, DATAPROPERTY_HAS_COMPARATOR,
comparator);
}
OWLUtils.addDataProperty(virtualPackageIndiv, ontology, df, manager, DATAPROPERTY_HAS_NAME, targetPackageName);
// relate this package with reference individual (VersionedPackage)
OWLUtils.createRelation(packageIndiv, virtualPackageIndiv, ontology, df, manager, property);
// relate create reference individual (VersionedPackage) with target indiv
OWLNamedIndividual targetPackage = getOrCreateTargetIndiv(packageNameMap, indivMap, df, manager, ontologyIRI,
ontology, targetPackageName);
OWLUtils.createRelation(virtualPackageIndiv, targetPackage, ontology, df, manager, OBJECTROPERTY_REALIZED_BY);
// add the owl value assertion, to be assembled later
OWLObjectHasValueImpl objectHasValueExpression = new OWLObjectHasValueImpl(OBJECTPROPERTY_CUDF_DEPENDS,
virtualPackageIndiv);
return objectHasValueExpression;
}
public static OWLNamedIndividual getOrCreateTargetIndiv(Map<String, Package> packageNameMap,
HashMap<Package, OWLNamedIndividual> indivMap, OWLDataFactory df, OWLOntologyManager manager,
IRI ontologyIRI, OWLOntologyImpl ontology, String targetPackageName) {
Package targetPackage = packageNameMap.get(targetPackageName);
OWLNamedIndividual targetIndiv = indivMap.get(targetPackage);
if (targetPackage == null) {
String targetPackageNamei386 = targetPackageName + ":i386";
boolean hasi386 = packageNameMap.containsKey(targetPackageNamei386);
System.out.println("No target package found for '" + targetPackageName + "'; found as "
+ targetPackageNamei386 + "'? " + (hasi386 ? " *** YES *** " // + "(" + packageNameMap.get(targetPackageNamei386) + ")"*/
: " -no- "));
}
if (targetPackage != null && targetIndiv == null) {
System.out.println("Package, but no target individual found for " + targetPackageName);
}
if (targetIndiv == null) {
// Create target individual on the sport
targetIndiv = OWLUtils.createAndRegisterIndividual(ontologyIRI.toString(), targetPackageName,
VirtualPackageAlternativeIdentifier.CLASS_CUDF_PACKAGE, df, manager, ontology);
// TODO: register it anywhere in a map?
// indivMap.put(targetPackageName, targetIndiv);
}
return targetIndiv;
}
}
class PackgeDetailsTask implements Callable<Package> {
static final Logger logPackageDetails = Logger.getLogger("PackaDetailsQuery");
private final String packageName;
public PackgeDetailsTask(String packageName) {
this.packageName = packageName;
}
@Override
public Package call() {
Package pkg = new Package();
pkg.setName(packageName);
String aptShowCommand = "aptitude show " + packageName;
aptShowCommand = "apt-cache show " + packageName;
ProcessBuilder processBuilder = new ProcessBuilder(new String[] { "/bin/sh", "-c", aptShowCommand });
logPackageDetails.info("Querying " + packageName);
try {
Process process = processBuilder.start();
// read package details into a data structure
List<String> intialPackageLines;
intialPackageLines = IOUtils.readLines(process.getInputStream());
// process elements that span multi-lines
ArrayList<String> processedPackageLines = new ArrayList<String>();
for (String string : intialPackageLines) {
if (string.startsWith(" ")) {
int index = processedPackageLines.size() - 1;
String line = processedPackageLines.get(index) + System.getProperty("line.separator") + string;
processedPackageLines.remove(index);
processedPackageLines.add(line);
} else {
processedPackageLines.add(string);
}
}
pkg.setPackageInformation(processedPackageLines);
logPackageDetails.info("\tfinished " + packageName);
return pkg;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
}