blob: 567e374d0a3e9dc104c7d03115f7a1203f2e4048 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.felix.obr.plugin;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
* Clean an OBR repository by finding and removing missing resources.
* @goal clean
* @phase install
* @requiresDependencyResolution compile
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public class ObrCleanRepo extends AbstractMojo {
/**
* OBR Repository.
*
* @parameter expression="${obrRepository}"
*/
private String obrRepository;
/**
* Local Repository.
*
* @parameter expression="${localRepository}"
* @required
* @readonly
*/
private ArtifactRepository localRepository;
public void execute() throws MojoExecutionException {
// If no OBR repository, return
if ("NONE".equalsIgnoreCase(obrRepository)) {
return;
}
try {
// Compute local repository location
String localRepoPath = localRepository.getBasedir();
PathFile repositoryXml = normalizeRepositoryPath(obrRepository, localRepoPath);
// Check if the file exist
if (!repositoryXml.isExists()) {
getLog().error("The repository file " + repositoryXml.getAbsoluteFilename() + " does not exist");
return;
}
Document doc = parseFile(repositoryXml.getFile(), initConstructor());
Node finalDocument = cleanDocument(doc.getDocumentElement()); //Analyze existing repository.
if (finalDocument == null) {
getLog().info("Nothing to clean in " + repositoryXml.getAbsoluteFilename());
} else {
getLog().info("Cleaning...");
writeToFile(repositoryXml.getUri(), finalDocument); // Write the new file
getLog().info("Repository " + repositoryXml.getAbsoluteFilename() + " updated");
}
} catch (Exception e) {
getLog().error("Exception while cleaning the OBR repository file : " + e.getLocalizedMessage(), e);
}
}
/**
* Analyze the given XML tree (DOM of the repository file) and remove missing resources.
* @param elem : the input XML tree
* @return the cleaned XML tree
*/
private Element cleanDocument(Element elem) {
NodeList nodes = elem.getElementsByTagName("resource");
List toRemove = new ArrayList();
// First, look for missing resources
for (int i = 0; i < nodes.getLength(); i++) {
Element n = (Element) nodes.item(i);
String value = n.getAttribute("uri");
String localRepoPath = localRepository.getBasedir();
File file = new File(localRepoPath, value);
if (!file.exists()) {
getLog().info(
"The bundle " + n.getAttribute("presentationname") + " - " + n.getAttribute("version")
+ " will be removed");
toRemove.add(n);
}
}
if (toRemove.size() > 0) {
// Then remove missing resources.
for (int i = 0; i < toRemove.size(); i++) {
elem.removeChild((Node) toRemove.get(i));
}
// If we have to remove resources, we need to update 'lastmodified' attribute
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss.SSS");
Date d = new Date();
d.setTime(System.currentTimeMillis());
elem.setAttribute("lastmodified", format.format(d));
return elem;
} else {
return null;
}
}
/**
* Initialize the document builder from Xerces.
* @return DocumentBuilder ready to create new document
* @throws MojoExecutionException : occurs when the instantiation of the document builder fails
*/
private DocumentBuilder initConstructor() throws MojoExecutionException {
DocumentBuilder constructor = null;
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
try {
constructor = factory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
getLog().error("Unable to create a new xml document");
throw new MojoExecutionException("Cannot create the Document Builder : " + e.getMessage());
}
return constructor;
}
/**
* Open an XML file.
* @param filename : XML file path
* @param constructor DocumentBuilder get from xerces
* @return Document which describes this file
* @throws MojoExecutionException occurs when the given file cannot be opened or is a valid XML file.
*/
private Document parseFile(File file, DocumentBuilder constructor) throws MojoExecutionException {
if (constructor == null) {
return null;
}
// The document is the root of the DOM tree.
getLog().info("Parsing " + file.getAbsolutePath());
Document doc = null;
try {
doc = constructor.parse(file);
} catch (SAXException e) {
getLog().error("Cannot parse " + file.getAbsolutePath() + " : " + e.getMessage());
throw new MojoExecutionException("Cannot parse " + file.getAbsolutePath() + " : " + e.getMessage());
} catch (IOException e) {
getLog().error("Cannot open " + file.getAbsolutePath() + " : " + e.getMessage());
throw new MojoExecutionException("Cannot open " + file.getAbsolutePath() + " : " + e.getMessage());
}
return doc;
}
/**
* write a Node in a xml file.
* @param outputFilename URI to the output file
* @param treeToBeWrite Node root of the tree to be write in file
* @throws MojoExecutionException if the plugin failed
*/
private void writeToFile(URI outputFilename, Node treeToBeWrite) throws MojoExecutionException {
// init the transformer
Transformer transformer = null;
TransformerFactory tfabrique = TransformerFactory.newInstance();
try {
transformer = tfabrique.newTransformer();
} catch (TransformerConfigurationException e) {
getLog().error("Unable to write to file: " + outputFilename.toString());
throw new MojoExecutionException("Unable to write to file: " + outputFilename.toString() + " : " + e.getMessage());
}
Properties proprietes = new Properties();
proprietes.put("method", "xml");
proprietes.put("version", "1.0");
proprietes.put("encoding", "ISO-8859-1");
proprietes.put("standalone", "yes");
proprietes.put("indent", "yes");
proprietes.put("omit-xml-declaration", "no");
transformer.setOutputProperties(proprietes);
DOMSource input = new DOMSource(treeToBeWrite);
File fichier = new File(outputFilename);
FileOutputStream flux = null;
try {
flux = new FileOutputStream(fichier);
} catch (FileNotFoundException e) {
getLog().error("Unable to write to file: " + fichier.getName());
throw new MojoExecutionException("Unable to write to file: " + fichier.getName() + " : " + e.getMessage());
}
Result output = new StreamResult(flux);
try {
transformer.transform(input, output);
} catch (TransformerException e) {
throw new MojoExecutionException("Unable to write to file: " + outputFilename.toString() + " : " + e.getMessage());
}
try {
flux.flush();
flux.close();
} catch (IOException e) {
throw new MojoExecutionException("IOException when closing file : " + e.getMessage());
}
}
private static PathFile normalizeRepositoryPath(String obrPath, String mavenPath) {
if (null == obrPath || obrPath.length() == 0) {
obrPath = mavenPath + File.separatorChar + "repository.xml";
} else if (!obrPath.endsWith(".xml")) {
obrPath = obrPath + File.separatorChar + "repository.xml";
}
URI uri;
try {
uri = new URI(obrPath);
} catch (URISyntaxException e) {
uri = null;
}
if (null == uri || !uri.isAbsolute()) {
File file = new File(obrPath);
if (!file.isAbsolute()) {
file = new File(mavenPath, obrPath);
}
uri = file.toURI();
}
return new PathFile(uri.toASCIIString());
}
}