package org.jboss.tools.license;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileReader;
import java.io.IOException;
import java.io.FileWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
public class ValidateLicenseHeaders
{
static final String DEFAULT_HEADER = "/*\n" +
"* JBoss, Home of Professional Open Source\n" +
"*\n" +
"* Distributable under LGPL license.\n" +
"* See terms of license at gnu.org.\n" +
"*/\n";
static Logger log = Logger.getLogger("ValidateCopyrightHeaders");
static FileFilter dotJavaFilter = new DotJavaFilter();
static HashMap licenseHeaders = new HashMap();
static ArrayList noheaders = new ArrayList();
static ArrayList invalidheaders = new ArrayList();
static int totalCount;
public static void main(String[] args)
throws Exception
{
if( args.length != 1 || args[0].startsWith("-h") )
{
log.info("Usage: ValidateLicenseHeaders jboss-src-root");
System.exit(1);
}
File jbossSrcRoot = new File(args[0]);
if( jbossSrcRoot.exists() == false )
{
log.info("Src root does not exist, check "+jbossSrcRoot.getAbsolutePath());
System.exit(1);
}
File licenseInfo = new File(jbossSrcRoot, "thirdparty/licenses/thirdparty-licenses.xml");
if( licenseInfo.exists() == false )
{
log.severe("Failed to find the thirdparty/licenses/thirdparty-licenses.xml under the src root");
System.exit(1);
}
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder db = factory.newDocumentBuilder();
Document doc = db.parse(licenseInfo);
NodeList licenses = doc.getElementsByTagName("license");
for(int i = 0; i < licenses.getLength(); i ++)
{
Element license = (Element) licenses.item(i);
String key = license.getAttribute("id");
ArrayList headers = new ArrayList();
licenseHeaders.put(key, headers);
NodeList copyrights = license.getElementsByTagName("terms-header");
for(int j = 0; j < copyrights.getLength(); j ++)
{
Element copyright = (Element) copyrights.item(j);
copyright.normalize();
String id = copyright.getAttribute("id");
String text = getElementContent(copyright);
if( text == null )
continue;
text = text.replaceAll("[\\s*]+", " ");
if( text.length() == 1)
continue;
text = text.toLowerCase();
LicenseHeader lh = new LicenseHeader(id, text);
headers.add(lh);
}
}
log.fine(licenseHeaders.toString());
File[] files = jbossSrcRoot.listFiles(dotJavaFilter);
log.info("Root files count: "+files.length);
processSourceFiles(files, 0);
log.info("Processed "+totalCount);
log.info("Files with no headers: "+noheaders.size());
FileWriter fw = new FileWriter("NoHeaders.txt");
for(Iterator iter = noheaders.iterator(); iter.hasNext();)
{
File f = (File) iter.next();
fw.write(f.getAbsolutePath());
fw.write('\n');
}
fw.close();
log.info("Files with invalid headers: "+invalidheaders.size());
fw = new FileWriter("InvalidHeaders.txt");
for(Iterator iter = invalidheaders.iterator(); iter.hasNext();)
{
File f = (File) iter.next();
fw.write(f.getAbsolutePath());
fw.write('\n');
}
fw.close();
}
public static String getElementContent(Element element)
{
if (element == null)
return null;
NodeList children = element.getChildNodes();
StringBuffer result = new StringBuffer();
for (int i = 0; i < children.getLength(); i++)
{
Node child = children.item(i);
if (child.getNodeType() == Node.TEXT_NODE ||
child.getNodeType() == Node.CDATA_SECTION_NODE)
{
result.append(child.getNodeValue());
}
else if( child.getNodeType() == Node.COMMENT_NODE )
{
}
else
{
result.append(child.getFirstChild());
}
}
return result.toString().trim();
}
static void processSourceFiles(File[] files, int level)
throws IOException
{
for(int i = 0; i < files.length; i ++)
{
File f = files[i];
if( level == 0 )
log.info("processing "+f);
if( f.isDirectory() )
{
File[] children = f.listFiles(dotJavaFilter);
processSourceFiles(children, level+1);
}
else
{
parseHeader(f);
}
}
}
static void parseHeader(File javaFile)
throws IOException
{
totalCount ++;
FileReader fr = new FileReader(javaFile);
BufferedReader br = new BufferedReader(fr);
String line = br.readLine();
StringBuffer tmp = new StringBuffer();
while( line != null )
{
line = line.trim();
if( line.startsWith("package") || line.startsWith("import") )
break;
if( line.startsWith("//") )
{
line = br.readLine();
continue;
}
if( line.startsWith("/**") )
tmp.append(line.substring(3));
else if( line.startsWith("/*") )
tmp.append(line.substring(2));
else if( line.startsWith("*") )
tmp.append(line.substring(1));
else
tmp.append(line);
tmp.append(' ');
line = br.readLine();
}
br.close();
fr.close();
if( tmp.length() == 0 )
{
addDefaultHeader(javaFile);
return;
}
String text = tmp.toString();
text = text.replaceAll("[\\s*]+", " ");
if( tmp.length() == 1 )
{
addDefaultHeader(javaFile);
return;
}
text = text.toLowerCase();
boolean matches = false;
Iterator iter = licenseHeaders.values().iterator();
escape:
while( iter.hasNext() )
{
List list = (List) iter.next();
Iterator jiter = list.iterator();
while( jiter.hasNext() )
{
LicenseHeader lh = (LicenseHeader) jiter.next();
if( text.startsWith(lh.text) )
{
matches = true;
if( log.isLoggable(Level.FINE) )
log.fine(javaFile+" matches copyright "+lh.id);
break escape;
}
else if( javaFile.getName().equals("CompressionConstants.java") )
{
log.fine("Does not match: "+lh.id);
}
}
}
text = null;
tmp.setLength(0);
if( matches == false )
invalidheaders.add(javaFile);
}
static void addDefaultHeader(File javaFile)
throws IOException
{
FileInputStream fis = new FileInputStream(javaFile);
FileChannel fc = fis.getChannel();
int size = (int) fc.size();
ByteBuffer contents = ByteBuffer.allocate(size);
fc.read(contents);
fis.close();
ByteBuffer hdr = ByteBuffer.wrap(DEFAULT_HEADER.getBytes());
FileOutputStream fos = new FileOutputStream(javaFile);
fos.write(hdr.array());
fos.write(contents.array());
fos.close();
noheaders.add(javaFile);
}
static class LicenseHeader
{
String id;
String text;
LicenseHeader(String id, String text)
{
this.id = id;
this.text = text;
}
}
static class DotJavaFilter implements FileFilter
{
public boolean accept(File pathname)
{
boolean accept = false;
String name = pathname.getName();
if( pathname.isDirectory() )
{
accept = name.equals("gen-src") == false
&& name.equals("gen-parsers") == false;
}
else
{
accept = name.endsWith("_Stub.java") == false && name.endsWith(".java");
}
return accept;
}
}
}