You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by cl...@apache.org on 2009/04/08 14:30:29 UTC

svn commit: r763213 [2/2] - in /felix/sandbox/clement/Project-Checker: ./ .settings/ libs/ licenses/ src/ src/org/ src/org/apache/ src/org/apache/felix/ src/org/apache/felix/project/ src/org/apache/felix/project/checker/

Added: felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/Project.java
URL: http://svn.apache.org/viewvc/felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/Project.java?rev=763213&view=auto
==============================================================================
--- felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/Project.java (added)
+++ felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/Project.java Wed Apr  8 12:30:27 2009
@@ -0,0 +1,519 @@
+package org.apache.felix.project.checker;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.text.DateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.jar.JarFile;
+import java.util.zip.ZipEntry;
+
+import javax.swing.text.html.parser.ParserDelegator;
+
+public class Project {
+    
+    public static final String CONFIG_FILE= "config.properties";
+
+    private static final String LICENSE_REPOSITORY = "licenses";
+
+    private static final int PROJECT_MODE = 0;
+    private static final int RELEASE_MODE = 1;
+    
+    public static final String UNZIP_PROPERTY = "UNZIP"; 
+    
+    private URL url;
+    private String name;
+    private String version;
+    private File directory; 
+    
+    private Properties props;
+    
+    private Map<String, File> artifacts = new HashMap<String, File>();
+
+    private Notice notice;
+    
+    private Date downloadDate;
+    
+    private List<Checker> checkers = new ArrayList<Checker>();
+    
+    private List<Checker> success = new ArrayList<Checker>();
+    
+    private List<Checker> skipped = new ArrayList<Checker>();
+
+    private Map<Checker, List<String>> warning = new HashMap<Checker, List<String>>();
+
+    private Map<Checker, List<String>> error = new HashMap<Checker, List<String>>();
+
+    private List<License> licences;
+    
+    private int mode;
+
+    private File root;
+
+    private JarFile jar;
+    
+    public Project(String url, String name, String version, boolean project_mode) throws FileNotFoundException, IOException {
+        this(url, name, version, CONFIG_FILE, project_mode);
+    }
+    
+    public Project(String url, String name, String version, String configuration, boolean project_mode) throws FileNotFoundException, IOException {
+        if (project_mode) {
+            mode = PROJECT_MODE;
+        } else {
+            mode = RELEASE_MODE;
+        }
+        
+        // Load configuration.
+        props = new Properties();
+        props.load(new FileInputStream(new File(configuration)));
+       
+        
+        // Set project name and version
+        this.name = name;
+        this.version = version;
+        
+        assert(this.name != null);
+        assert(this.version != null);
+        
+        checkers = new ArrayList<Checker>();
+        
+        // Add default checkers.
+        checkers.add(new ProjectLicenseChecker());
+        checkers.add(new ProjectNoticeChecker());
+        checkers.add(new JarNoticeChecker());
+        checkers.add(new JarLicenseChecker());
+        checkers.add(new HeaderChecker());
+        checkers.add(new LicenseSummaryChecker());
+        checkers.add(new NoticeNameChecker());
+        checkers.add(new NoticeCopyrightChecker());
+        checkers.add(new IncludedApacheLicence());
+        checkers.add(new IncludedLicenseChecker());
+        checkers.add(new UsedLicenseChecker());
+
+        
+        // if release mode, create the temporary directory
+        if (mode == RELEASE_MODE) {
+            directory = new File("release-" + name + "-" + version);
+            this.url = new URL(url);
+            
+            checkers.add(new FileChecker());
+            checkers.add(new SignatureBeautifiedChecker());
+            checkers.add(new SignatureChecker());
+            checkers.add(new MD5Checker());
+            checkers.add(new Sha1Checker());
+            checkers.add(new ChangelogChecker());
+            checkers.add(new TagChecker());
+        } else {
+            root = new File(url);
+            directory = new File(root, "target");
+        }
+    }
+    
+    public Notice getNotice() {
+        return notice;
+    }
+    
+    public String getProperty(String name) {
+        return props.getProperty(name);
+    }
+    
+    public List<License> getKnownLicense() {
+        return licences;
+    }
+    
+    public void download() throws Exception {
+        Map<String, URL> urls = getURLs();
+       
+        
+        directory.mkdir();
+        Iterator<String> it = urls.keySet().iterator();
+        
+        while(it.hasNext()) {
+            String name = it.next();
+            URL url = urls.get(name);
+
+            System.out.println("Downloading " + name);
+            downloadDate = new Date();
+            
+            File file = new File(directory, name);
+            directory.mkdirs();
+            FileOutputStream writer = new FileOutputStream(file);
+            InputStream is = url.openStream();
+            int cc = 0;
+            do {
+                int i = is.read();
+                if (i == -1)
+                    break;
+                cc++;
+                writer.write(i);
+            } while (true);
+            
+            is.close();
+            writer.close();
+            
+            System.out.println(name + " downloaded");
+            
+        }
+        
+    }
+    
+    private void prepareProjectMode() throws Exception {
+        // Check that the root as a pom files, and the jar file exists.
+        File pom = new File(root, "pom.xml");
+        if (! pom.exists()) {
+            throw new Exception("No pom file in the directory " + root.getAbsolutePath());
+        }
+        
+        File jarF = new File(root, "target/" + name + "-" + version + ".jar");
+        System.out.println(jarF.getAbsolutePath());
+        if (! jarF.exists()) {
+            throw new Exception("No jar file in the target directory");
+        }
+        
+        jar = new JarFile(jarF);
+        
+        artifacts.put(jarF.getName(), jarF);
+        
+    }
+    
+    private void prepareReleaseMode() throws Exception {
+        // Compute the project artifacts
+        File[] files = getArtifactDirectory().listFiles();
+        for (int i = 0; i < files.length; i++) {
+            artifacts.put(files[i].getName(), files[i]);
+        }
+        
+        // Get the Jar file
+        // Extract the notice and parse it.
+        Iterator<String> it = artifacts.keySet().iterator();
+        File project = null;
+        while(it.hasNext()) {
+            String f = it.next();
+            if (f.endsWith(getVersion() + ".jar")) { // Avoid sources.
+                jar = new JarFile(artifacts.get(f));
+            }
+            if (f.endsWith(getVersion() + "-project.zip")) { 
+                project = artifacts.get(f);
+            }
+        }
+        
+        if (jar == null) {
+            throw new Exception("Cannot prepare the checking : No Jar file !");
+        }
+        
+        if (project == null) {
+            throw new Exception("Cannot prepare the checking : No project file !");
+        }
+        
+        // Unzip the project file
+        Command cmd = new Command();
+        cmd.executeCommand(this, getProperty(UNZIP_PROPERTY) + " -u " + project.getName(), false);
+       
+        root = new File(directory, name + "-" + version);
+        if (! root.exists()) {
+            throw new Exception("Cannot prepare the checking : Project cannot be unzipped !");
+        }
+        
+        
+       
+    }
+    
+    public void prepareChecking() throws Exception {
+        File repo = new File(LICENSE_REPOSITORY);
+        licences = LicenseParser.getKnownLicenses(repo);
+
+        if (mode == PROJECT_MODE) {
+            prepareProjectMode();
+        } else {
+            prepareReleaseMode();
+        }
+      
+        // Get notice
+        ZipEntry ze = jar.getEntry("META-INF/NOTICE");
+        InputStream is = jar.getInputStream(ze);
+        File not = new File(getArtifactDirectory(), "NOTICE");
+        FileOutputStream os = new FileOutputStream(not);
+        int c;
+        int i = 0;
+        while ((c = is.read()) >= 0) {
+            os.write(c);
+            i++;
+        }
+        is.close();
+        
+        notice = new Notice(not);
+         
+    }
+    
+    private Map<String, URL> getURLs() throws Exception {
+        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+        System.out.println("Opening stream " + url);
+
+        InputStream is = connection.getInputStream();
+        
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+        int cc = 0;
+        do {
+            int i = is.read();
+            if (i == -1)
+                break;
+            cc++;
+            bos.write(i);
+        } while (true);
+
+
+        byte[] bytes = bos.toByteArray();
+
+        try {
+            bos.close();
+            is.close();
+            connection.disconnect();
+        } catch (Exception e) {
+           throw new Exception("Cannot get urls : " + e.getMessage());
+        }
+        
+        return computeURLs(bytes);    
+    }
+
+    private Map<String, URL> computeURLs(byte[] stream) throws IOException {
+        try {
+            BufferedReader   reader = new BufferedReader(new StringReader(new String(stream)));
+            LinkCollector lk = new LinkCollector(url, name);
+            new ParserDelegator().parse(reader,lk, true);
+            return lk.getlist();
+        }
+        catch (IOException ioe) {
+            System.out.println("IOE: " + ioe);
+        }
+        return null;
+
+    }
+    
+    public File getProjectRoot() {
+        assert root.exists();
+        return root;
+    }
+    
+    public JarFile getJar() {
+        assert jar != null;
+        return jar;
+    }
+    
+    public void check() throws Exception {
+        for (Checker chk : checkers) {
+                boolean ok = chk.prepare(this);
+                if (ok) {
+                    try {
+                        chk.check();
+                        chk.clean();
+                        if (! error.containsKey(chk)) {
+                            success(chk);
+                        }
+                    } catch (Exception e) {
+                        if (e.getCause() != null) {
+                            error(chk, e.getMessage(), e.getCause().getMessage());
+                        } else {
+                            error(chk, e.getMessage(), null);
+                        }
+                    }
+                } else {
+                    skipped.add(chk);
+                }
+        }
+        printReport();
+    }
+    
+    public void error(Checker chk, String error, String cause) {
+        List<String> list = this.error.get(chk);
+        if (list == null) {
+            list = new ArrayList<String>();
+            this.error.put(chk, list);
+        }
+        if (cause != null) {
+            String err = error + ":\n" + cause;
+            list.add(err);
+        } else {
+            list.add(error);
+        }
+    }
+    
+    public void warning(Checker chk, String message) {
+        List<String> list = this.warning.get(chk);
+        if (list == null) {
+            list = new ArrayList<String>();
+            this.warning.put(chk, list);
+        }
+        list.add(message);
+    }
+    
+    private void success(Checker chk) {
+        success.add(chk);
+    }
+    
+    public static void main(String[] args) throws Exception {
+        String url = null;
+        String name = null;
+        String version = null;
+        String configuration = null;
+        boolean download = true;
+        boolean project = false;
+        for (int i = 0; i < args.length; i++) {
+            if (! args[i].contains("-")) {
+                continue; // Skip the value.
+            }
+            if (args[i].equals("-u") || args[i].equals("--url")) {
+                url = args[i+1];
+                project = false;
+            }
+            if (args[i].equals("-n") || args[i].equals("--name")) {
+                name = args[i+1];
+            }
+            if (args[i].equals("-v") || args[i].equals("--version")) {
+                version = args[i+1];
+            }
+            if (args[i].equals("-c") || args[i].equals("--config")) {
+                configuration = args[i+1];
+            }
+            if (args[i].equals("-o") || args[i].equals("--offline")) {
+                download = false;
+            }
+            if (args[i].equals("-d") || args[i].equals("--directory")) {
+                url = args[i+1];
+                project = true;
+            }
+        }
+        
+        if (url == null || name == null || version == null) {
+            printUsage();
+            return;
+        }
+        Project release = null;
+        if (configuration == null) {
+            release = new Project(url, name, version, project);
+        } else {
+            release = new Project(url, name, version, configuration, project);
+        }
+        
+        if (! project && download) {
+            release.download();
+        }
+        
+        release.prepareChecking();
+        release.check();
+        release.clean();
+        
+        
+       // Release release = new Release("http://people.apache.org/~pauls/1.6.0/", "org.apache.felix.bundlerepository", "1.4.0");
+       // Release release = new Release("http://people.apache.org/~clement/releases/org/apache/felix/org.apache.felix.http.jetty/1.0.0/", "org.apache.felix.http.jetty", "1.0.0"); 
+       // release.download();
+    }
+
+    private static void printUsage() {
+       StringBuffer usage = new StringBuffer();
+
+       usage.append("Release-Checker is just a small tool checking releases \n");
+       usage.append("How to launch:\n");
+       usage.append("java -cp bin:commons-cli-1.1.jar:commons-collections-3.2.1.jar:commons-lang-2.4.jar:dom4j-1.6.1.jar:apache-rat-0.7-SNAPSHOT.jar:apache-rat-core-0.7-SNAPSHOT.jar org.apache.felix.release.checker.Release [ARGS]\n");
+       usage.append("Arguments:\n");
+       usage.append("\t -u or --url: URL to download the release [mandatory] \n");
+       usage.append("\t -n or --name: Name of the artifact [mandatory] \n");
+       usage.append("\t -v or --version: Version of the artifact [mandatory] \n");
+       usage.append("\t -c or --configuration: Set the configuration file to use \n");
+       usage.append("Example:\n");
+       usage.append("java -cp bin:commons-cli-1.1.jar:commons-collections-3.2.1.jar:commons-lang-2.4.jar:dom4j-1.6.1.jar:apache-rat-0.7-SNAPSHOT.jar:apache-rat-core-0.7-SNAPSHOT.jar org.apache.felix.release.checker.Release -u http://people.apache.org/~pauls/1.6.0/ -n org.apache.felix.bundlerepository -v 1.4.0 --offline");
+       
+       System.out.println(usage);
+       
+    }
+
+    public void clean() {
+       directory.delete();
+    }
+
+    public Map<String, File> getArtifacts()  {
+        return artifacts;
+    }
+
+    public File getArtifactDirectory() {
+        return directory;
+    }
+
+    public String getName() {
+        return name;
+    }
+    
+    public String getVersion() {
+        return version;
+    }
+    
+    private void printReport() {
+        StringBuffer report = new StringBuffer();
+        // Header
+        report.append("============================================================\n");
+        report.append("=                  Release Checking Report                 =\n");
+        report.append("============================================================\n");
+        report.append("\n");
+        report.append("I. Overview:\n");
+        report.append("\t Artifact name: " + name + "\n");
+        report.append("\t Artifact version: " + version + "\n");
+        if (downloadDate != null) {
+            report.append("\t Download date: " + DateFormat.getDateTimeInstance().format(downloadDate) + "\n");
+        }
+        report.append("\t Number of download files: " + artifacts.size() + "\n");
+        report.append("\t Directory: " + directory.getAbsolutePath() + "\n");
+        report.append("\n");
+        report.append("II. Result Overview:\n");
+        report.append("\t Number of checkers: " + checkers.size());
+        report.append("\t Success: " + success.size());
+        report.append("\t Warnings: " + warning.size());
+        report.append("\t Errors: " + error.size());
+        report.append("\t Skipped: " + skipped.size());
+        report.append("\n");
+        report.append("\n");
+        report.append("II. Result Details:\n");
+        for(Checker chk: checkers) {
+            String result = "\t[" + chk.getCheckerName() + "] ";
+            if (success.contains(chk)) {
+                if (warning.containsKey(chk)) {
+                    result += " OK with warnings: \n";
+                    List<String> warnings = warning.get(chk);
+                    for(String warn:warnings) {
+                        result += "\t\t[WARNING] " + warn +"\n";
+                    }
+                } else {
+                    result +=  " OK \n";
+                }
+            } else if (skipped.contains(chk)) {
+                result +=  " SKIPPED \n";
+            } else { // Failure
+                result += " FAILURE: \n";
+                List<String> err = error.get(chk);
+                for(String mess:err) {
+                    result += "\t\t[ERROR] " + mess +"\n";
+                }
+            }
+            report.append(result);
+        }
+        
+        report.append("============================================================\n");
+        
+        System.out.println(report);
+    }
+
+
+}

Added: felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/ProjectLicenseChecker.java
URL: http://svn.apache.org/viewvc/felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/ProjectLicenseChecker.java?rev=763213&view=auto
==============================================================================
--- felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/ProjectLicenseChecker.java (added)
+++ felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/ProjectLicenseChecker.java Wed Apr  8 12:30:27 2009
@@ -0,0 +1,31 @@
+package org.apache.felix.project.checker;
+
+import java.io.File;
+
+public class ProjectLicenseChecker implements Checker {
+    
+    private Project release;
+
+    public void check() throws Exception {
+        File file = new File(release.getProjectRoot(), "LICENSE");
+        if (! file.exists()) {
+            file = new File(release.getProjectRoot(), "LICENCE");
+            if (! file.exists()) {
+                throw new Exception("Cannot find license file in " + file.getName());
+            }
+        }
+    }
+
+    public void clean() {    }
+
+    public boolean prepare(Project release) throws Exception {
+        this.release = release; 
+        
+        return true;
+    }
+    
+    public String getCheckerName() {
+        return "Project License Checker";
+    }
+
+}

Added: felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/ProjectNoticeChecker.java
URL: http://svn.apache.org/viewvc/felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/ProjectNoticeChecker.java?rev=763213&view=auto
==============================================================================
--- felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/ProjectNoticeChecker.java (added)
+++ felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/ProjectNoticeChecker.java Wed Apr  8 12:30:27 2009
@@ -0,0 +1,27 @@
+package org.apache.felix.project.checker;
+
+import java.io.File;
+
+public class ProjectNoticeChecker implements Checker {
+    private Project release;
+
+    public void check() throws Exception {
+        File file = new File(release.getProjectRoot(), "NOTICE");
+        if (!file.exists()) {
+            throw new Exception("Cannot find license file in " + file.getName());
+        }
+
+    }
+
+    public void clean() {    }
+
+    public boolean prepare(Project release) throws Exception {
+        this.release = release; 
+        return true;
+    }
+    
+    public String getCheckerName() {
+        return "Project notice Checker";
+    }
+
+}

Added: felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/Sha1Checker.java
URL: http://svn.apache.org/viewvc/felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/Sha1Checker.java?rev=763213&view=auto
==============================================================================
--- felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/Sha1Checker.java (added)
+++ felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/Sha1Checker.java Wed Apr  8 12:30:27 2009
@@ -0,0 +1,66 @@
+package org.apache.felix.project.checker;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+public class Sha1Checker implements Checker {
+    
+    public static final String SSL_PROPERTY = "SSL"; 
+
+    private List<File> files = new ArrayList<File>();
+    private Project release;
+
+    public void check() throws Exception {
+        for (File f : files) {
+            // Remove the .sha1 from the file name
+            int index = f.getName().lastIndexOf('.');
+            String n = f.getName().substring(0, index);
+            
+            Command cmd = new Command();
+            cmd.executeCommand(release, release.getProperty(SSL_PROPERTY) + " sha1 " + n, false);
+            String out = cmd.getOutput();            
+            String md5 = getSha1(f);
+            if (! out.contains(md5)) {
+                throw new Exception("Bad sha1 hash for " + n);
+            }
+        }
+    }
+
+    private String getSha1(File f) throws IOException {
+        FileReader fis = new FileReader (f);
+        BufferedReader br = new BufferedReader (fis);
+        String line = br.readLine();
+        int index = line.indexOf(' ');
+        return line.substring(index).trim();
+    }
+
+    public void clean() {
+        files.clear();
+    }
+
+    public boolean prepare(Project release) throws Exception {
+        this.release = release;
+        // Get all md5 and sha1 files
+        Map<String, File> maps = release.getArtifacts();
+        Iterator<String> it = maps.keySet().iterator();
+        while(it.hasNext()) {
+            String f = it.next();
+            if (f.endsWith(".sha1")) {
+                files.add(maps.get(f));
+            }
+        }
+        
+        return true;
+    }
+    
+    public String getCheckerName() {
+        return "SHA1 Signature Checker";
+    }
+
+}

Added: felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/SignatureBeautifiedChecker.java
URL: http://svn.apache.org/viewvc/felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/SignatureBeautifiedChecker.java?rev=763213&view=auto
==============================================================================
--- felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/SignatureBeautifiedChecker.java (added)
+++ felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/SignatureBeautifiedChecker.java Wed Apr  8 12:30:27 2009
@@ -0,0 +1,63 @@
+package org.apache.felix.project.checker;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+public class SignatureBeautifiedChecker implements Checker {
+    
+    List<File> files = new ArrayList<File>();
+
+    public void check() throws Exception {
+        for (File f : files) {
+            FileReader fis = new FileReader (f);
+            BufferedReader br = new BufferedReader (fis);
+            String line = br.readLine();
+           
+            // Close the input stream
+            br.close();
+      
+            // Check format : signature filename
+            String[] array = line.split(" ");
+            if (array.length < 2) {
+                throw new Exception("Bad signature, file name sounds missing in " + f.getName());
+            }
+            
+            // Remove the .sha1 or .md5 from the file name
+            int index = f.getName().lastIndexOf('.');
+            String n = f.getName().substring(0, index);
+            
+            if (! line.contains(n)) {
+                throw new Exception("The file name is missing in " + f.getName());
+            }
+            
+        }
+    }
+
+    public void clean() {
+        files.clear();
+    }
+
+    public boolean prepare(Project release) throws Exception {
+        // Get all md5 and sha1 files
+        Map<String, File> maps = release.getArtifacts();
+        Iterator<String> it = maps.keySet().iterator();
+        while(it.hasNext()) {
+            String f = it.next();
+            if (f.endsWith(".md5")  || f.endsWith(".sha1")) {
+                files.add(maps.get(f));
+            }
+        }
+        
+        return true;
+    }
+    
+    public String getCheckerName() {
+        return "Signature beautification Checker";
+    }
+
+}

Added: felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/SignatureChecker.java
URL: http://svn.apache.org/viewvc/felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/SignatureChecker.java?rev=763213&view=auto
==============================================================================
--- felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/SignatureChecker.java (added)
+++ felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/SignatureChecker.java Wed Apr  8 12:30:27 2009
@@ -0,0 +1,51 @@
+package org.apache.felix.project.checker;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+public class SignatureChecker implements Checker {
+    
+    private List<File> files = new ArrayList<File>();
+    private Project release;
+
+    public void check() throws Exception {
+        for (File f : files) {
+            // Remove the .asc from the file name
+            int index = f.getName().lastIndexOf('.');
+            String n = f.getName().substring(0, index);
+            
+            Command cmd = new Command();
+            cmd.executeCommand(release, "/usr/local/bin/gpg --verify " + f.getName() + " " + n, false);
+            String err = cmd.getError();
+            if (!err.contains("(CODE SIGNING KEY)")) {
+                throw new Exception("Cannot verify the signature of " + n + " : " + err);
+            }
+        }
+    }
+
+    public void clean() {
+        files.clear();
+    }
+
+    public boolean prepare(Project release) throws Exception {
+        this.release = release;
+        // Get all md5 and sha1 files
+        Map<String, File> maps = release.getArtifacts();
+        Iterator<String> it = maps.keySet().iterator();
+        while(it.hasNext()) {
+            String f = it.next();
+            if (f.endsWith(".asc")) {
+                files.add(maps.get(f));
+            }
+        }
+        return true;
+    }
+    
+    public String getCheckerName() {
+        return "ASC signature Checker";
+    }
+
+}

Added: felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/TagChecker.java
URL: http://svn.apache.org/viewvc/felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/TagChecker.java?rev=763213&view=auto
==============================================================================
--- felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/TagChecker.java (added)
+++ felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/TagChecker.java Wed Apr  8 12:30:27 2009
@@ -0,0 +1,125 @@
+package org.apache.felix.project.checker;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.swing.text.MutableAttributeSet;
+import javax.swing.text.html.HTML;
+import javax.swing.text.html.HTMLEditorKit;
+import javax.swing.text.html.parser.ParserDelegator;
+
+public class TagChecker implements Checker {
+    
+    public static final String SVN_URL="SVN_URL";
+    public static final String TITLE_REGEX = ".* - Revision (.*): (.*)";
+    public static final Pattern TITLE_PATTERN = Pattern.compile(TITLE_REGEX);
+    
+    
+    private URL url;
+    private String name;
+    private String version;
+
+    public void check() throws Exception {
+        // Load the page and check that the title is correct
+       
+        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+        System.out.println("Opening stream " + url);
+
+        InputStream is = connection.getInputStream();
+        
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+        int cc = 0;
+        do {
+            int i = is.read();
+            if (i == -1)
+                break;
+            cc++;
+            bos.write(i);
+        } while (true);
+
+
+        byte[] bytes = bos.toByteArray();
+
+        try {
+            bos.close();
+            is.close();
+            connection.disconnect();
+        } catch (Exception e) {
+           throw new Exception("Cannot get urls : " + e.getMessage());
+        }
+        
+       parsePage(bytes);
+    }
+
+    public void clean() { }
+
+    public String getCheckerName() {
+       return "Release Tag Checker";
+    }
+
+    public boolean prepare(Project release) throws Exception {
+        String root = release.getProperty(SVN_URL);
+        if (root == null) {
+            return false;
+        } else {
+            url = new URL(root + release.getName() + "-" + release.getVersion());
+        }
+        
+        name = release.getName();
+        version = release.getVersion();
+        
+        return true;
+    }
+    
+    private void parsePage(byte[] bytes) throws Exception {
+        BufferedReader   reader = new BufferedReader(new StringReader(new String(bytes)));
+        Parser parser = new Parser();
+        new ParserDelegator().parse(reader,parser, true);
+        parseTitle(parser.title);
+
+    }
+    
+    private void parseTitle(String title) throws Exception {
+        Matcher matcher = TITLE_PATTERN.matcher(title);
+        if (matcher.matches()) {
+            String path = matcher.group(2);
+            if (! path.contains(name+"-"+version)) {
+                throw new Exception("Release revision page not valid, expected " + name+"-"+version + ", found " + path);
+            }
+            System.out.println("revision : " + matcher.group(1) + " - " + path);
+        } else {
+            throw new Exception("Release revision page not valid, expected " + TITLE_REGEX + ", found " + title);
+        }
+    }
+    
+    private class Parser extends HTMLEditorKit.ParserCallback {
+        private String title;
+        private boolean enable = false;
+
+        public void handleText(char[] data, int pos) {
+            if (enable) {
+                title = new String(data);
+            } 
+        }
+        
+        public void handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos) {
+            enable = t.equals(HTML.Tag.TITLE);
+        }
+        
+        public void handleEndTag(HTML.Tag t, int pos) {
+            if (enable) {
+                enable = false;
+            }
+        }
+    }
+
+
+
+}

Added: felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/UsedLicenseChecker.java
URL: http://svn.apache.org/viewvc/felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/UsedLicenseChecker.java?rev=763213&view=auto
==============================================================================
--- felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/UsedLicenseChecker.java (added)
+++ felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/UsedLicenseChecker.java Wed Apr  8 12:30:27 2009
@@ -0,0 +1,159 @@
+package org.apache.felix.project.checker;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.jar.JarFile;
+import java.util.zip.ZipEntry;
+
+public class UsedLicenseChecker implements Checker {
+
+    public static final String BUNDLE_MANIFEST_VERSION = "Bundle-ManifestVersion";
+    public static final String BUNDLE_IMPORT_PACKAGES = "Import-Package";
+
+    
+    private Project release;
+    private JarFile jar;
+    private List<String> packages;
+
+    public void check() throws Exception {
+        
+        
+        // filter(packages); // Remove apache (no filter)
+        check(packages); // Check the others references against the checkers.
+        
+        if (! packages.isEmpty()) {
+            // Unrecognized packages.
+            for (String r : packages) {
+                release.warning(this, "Cannot match " + r + " with a known license");
+            }
+        }
+    }
+    
+//    private void filter(List<String> referred) {
+//        List<String> toRemove = new ArrayList<String>();
+//        for (String s : referred) {
+//            if (s.startsWith("org.apache.")) {
+//                toRemove.add(s);
+//            }
+//        }
+//        referred.removeAll(toRemove);
+//    }
+    
+    private void check(List<String> referred) {
+        List<String> toRemove = new ArrayList<String>();
+        for (String s : referred) {
+            if (toRemove.contains(s)) {
+                continue; // Already checked.
+            }
+
+            License checker = getLicenseByPrefix(s);
+
+            if (checker != null) {
+                try {
+                    License found = getLicenseByKeyword(checker.getKeyword());
+                    checker.check(this, release, found);
+                    // Remove package.
+                    for (String x : referred) {
+                        if (x.startsWith(s)) {
+                            toRemove.add(x);
+                        }
+                    }
+                } catch (Exception e) {
+                    release.error(this, "Included code does not have an appropriate licence " + s, e.getMessage());
+                }
+            }
+            
+        }
+        referred.removeAll(toRemove);
+    }
+    
+    public License getLicenseByPrefix(String packagename) {
+        for (License checker : release.getKnownLicense()) {
+            for (int i = 0; i < checker.getPackages().length; i++) {
+                if (packagename.startsWith(checker.getPackages()[i])) {
+                    return checker;
+                }
+            }
+            
+        }
+        return null;
+    }
+    
+    public License getLicenseByKeyword(String key) {
+        Notice notice = release.getNotice();
+        License found = null;
+        List<License> lics = notice.getUsed();
+        for (License lic : lics) {
+            if (lic.getText().contains(key)) {
+                if (found == null) {
+                    found = lic;
+                } else {
+                    release.warning(this, "Ambiguity found when analyzing the notice file, several licenses match with " + key 
+                            + "(" + found.getProvider() + ", " + lic.getProvider() + ")");
+                }
+            } 
+        }
+        return found;
+    }
+
+    public void clean() {    }
+
+    public String getCheckerName() {
+        return "Used License Checker";
+    }
+
+    public boolean prepare(Project release) throws Exception {
+        this.release = release;
+        jar = release.getJar();
+        Object o = jar.getManifest().getMainAttributes().getValue(BUNDLE_MANIFEST_VERSION);
+        if (o == null) {
+            System.out.println("Not a bundle");
+            return false;
+        }
+        
+        String imports = (String) jar.getManifest().getMainAttributes().getValue(BUNDLE_IMPORT_PACKAGES);
+        processImports(imports);
+
+        
+        return true;
+    }
+    
+    private void processImports(String imports) {
+        // Remove '\n'
+        imports = imports.replaceAll("\n", "");
+        // Remove spaces
+        imports = imports.replaceAll(" ", "");
+        
+        String[] clauses = null;
+        
+        if (imports.contains(",")) {
+            clauses = imports.split(",");
+        } else {
+            clauses = new String[] {imports}; 
+        }
+        
+        packages = new ArrayList<String>();
+        for(String s : clauses) {
+            int index = s.indexOf(';');
+            if (index != -1) {
+                String pack = s.substring(0, index);
+                packages.add(pack);
+            } else {
+                packages.add(s);
+            }
+        }
+        
+        // Remove packages contained in the jar file
+        List<String> toRemove = new ArrayList<String>();
+        for (String s : packages) {
+            String directory = s.replace(".", "/");
+            ZipEntry je  = jar.getEntry(directory);
+            if (je != null) {
+                toRemove.add(s);
+            }
+        }
+        packages.removeAll(toRemove);
+        
+    }
+
+}

Added: felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/Utils.java
URL: http://svn.apache.org/viewvc/felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/Utils.java?rev=763213&view=auto
==============================================================================
--- felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/Utils.java (added)
+++ felix/sandbox/clement/Project-Checker/src/org/apache/felix/project/checker/Utils.java Wed Apr  8 12:30:27 2009
@@ -0,0 +1,79 @@
+package org.apache.felix.project.checker;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+public class Utils {
+    
+    public static File expand(File directory, String name, ZipEntry ze, ZipFile zf) throws IOException {
+        InputStream is = zf.getInputStream(ze);
+        File file = new File(directory,name);
+        FileOutputStream os = new FileOutputStream(file);
+        int c;
+        int i = 0;
+        while ((c = is.read()) >= 0) {
+            os.write(c);
+            i++;
+        }
+        is.close();
+        return file;
+    }
+    
+    public static boolean delete(File file) {
+        return file.delete();
+    }
+    
+    public static boolean compare(File a, File b) {
+        try {
+            
+        if (a == null && b != null) {
+            return false;
+        }
+        
+        if (b == null && a != null) {
+            return false;
+        }
+        
+        BufferedReader br1 = new BufferedReader(new FileReader(a));
+        BufferedReader br2 = new BufferedReader(new FileReader(b));
+        
+        StringBuffer report = new StringBuffer();
+        
+        String l1 = null;
+        String l2 = null;
+        while ((l1 = br1.readLine()) != null) {
+            l2 = br2.readLine();
+            if (! l1.equals(l2)) {
+                report.append("Expected : " + l1 + "\n");
+                report.append("Found : "+ l2 + "\n");
+                report.append("\n");
+            }
+        }
+        
+        br1.close();
+        br2.close();
+        
+        if (report.length() > 0) {
+            System.out.println("Differences found between " + a.getAbsolutePath() + " and " + a.getAbsolutePath());
+            System.out.println(report);
+            return false;
+        } else {
+            return true;
+        }
+        
+        } catch (IOException e) {
+            System.err.println("Issue occurs when comparing files " + e.getMessage());
+            return false;
+        }
+    }
+
+}