[jbosscache-commits] JBoss Cache SVN: r6775 - in core/trunk/src/test/java/org/jboss/cache/util: license and 1 other directory.

jbosscache-commits at lists.jboss.org jbosscache-commits at lists.jboss.org
Mon Sep 22 13:27:38 EDT 2008


Author: manik.surtani at jboss.com
Date: 2008-09-22 13:27:38 -0400 (Mon, 22 Sep 2008)
New Revision: 6775

Added:
   core/trunk/src/test/java/org/jboss/cache/util/license/
   core/trunk/src/test/java/org/jboss/cache/util/license/ValidateLicenseHeaders.java
Log:
Added util class to edit license headers

Added: core/trunk/src/test/java/org/jboss/cache/util/license/ValidateLicenseHeaders.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/util/license/ValidateLicenseHeaders.java	                        (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/util/license/ValidateLicenseHeaders.java	2008-09-22 17:27:38 UTC (rev 6775)
@@ -0,0 +1,516 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.cache.util.license;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.io.SyncFailedException;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * A utility which scans all java source files in the cvs tree and validates
+ * the license header prior to the package statement for headers that match
+ * those declared in thirdparty/licenses/license-info.xml
+ *
+ * @author Scott.Stark at jboss.org
+ * @version $Revision: 57184 $
+ */
+public class ValidateLicenseHeaders
+{
+   /**
+    * Used to strip out diffs due to copyright date ranges
+    */
+   static final String COPYRIGHT_REGEX = "copyright\\s(\\(c\\))*\\s*[\\d]+(\\s*,\\s*[\\d]+|\\s*-\\s*[\\d]+)*";
+
+   static final String DEFAULT_HEADER = "/*\n" +
+         " * JBoss, Home of Professional Open Source.\n" +
+         " * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors\n" +
+         " * as indicated by the @author tags. See the copyright.txt file in the\n" +
+         " * distribution for a full listing of individual contributors.\n" +
+         " *\n" +
+         " * This is free software; you can redistribute it and/or modify it\n" +
+         " * under the terms of the GNU Lesser General Public License as\n" +
+         " * published by the Free Software Foundation; either version 2.1 of\n" +
+         " * the License, or (at your option) any later version.\n" +
+         " *\n" +
+         " * This software is distributed in the hope that it will be useful,\n" +
+         " * but WITHOUT ANY WARRANTY; without even the implied warranty of\n" +
+         " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" +
+         " * Lesser General Public License for more details.\n" +
+         " *\n" +
+         " * You should have received a copy of the GNU Lesser General Public\n" +
+         " * License along with this software; if not, write to the Free\n" +
+         " * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA\n" +
+         " * 02110-1301 USA, or see the FSF site: http://www.fsf.org.\n" +
+         " */\n";
+   static Logger log = Logger.getLogger("ValidateCopyrightHeaders");
+   static boolean addDefaultHeader = false;
+   static FileFilter dotJavaFilter = new DotJavaFilter();
+   /**
+    * The term-headers from the thirdparty/license/license-info.xml
+    */
+   static TreeMap licenseHeaders = new TreeMap();
+   /**
+    * Java source files with no license header
+    */
+   static ArrayList noheaders = new ArrayList();
+   /**
+    * Java source files with a header that does not match one from licenseHeaders
+    */
+   static ArrayList invalidheaders = new ArrayList();
+   /**
+    * Total java source files seen
+    */
+   static int totalCount;
+   /**
+    * Total out of date jboss headers seen
+    */
+   static int jbossCount;
+
+   /**
+    * ValidateLicenseHeaders jboss-src-root
+    *
+    * @param args
+    */
+   public static void main(String[] args)
+         throws Exception
+   {
+      if (args.length == 0 || args[0].startsWith("-h"))
+      {
+         log.info("Usage: ValidateLicenseHeaders [-addheader] src-root");
+         System.exit(1);
+      }
+      int rootArg = 0;
+      if (args.length == 2)
+      {
+         if (args[0].startsWith("-add"))
+            addDefaultHeader = true;
+         else
+         {
+            log.severe("Uknown argument: " + args[0]);
+            log.info("Usage: ValidateLicenseHeaders [-addheader] src-root");
+            System.exit(1);
+
+         }
+         rootArg = 1;
+      }
+
+      File jbossSrcRoot = new File(args[rootArg]);
+      if (jbossSrcRoot.exists() == false)
+      {
+         log.info("Src root does not exist, check " + jbossSrcRoot.getAbsolutePath());
+         System.exit(1);
+      }
+
+//      URL u = Thread.currentThread().getContextClassLoader().getResource("META-INF/services/javax.xml.parsers.DocumentBuilderFactory");
+//      System.err.println(u);
+//
+//      // Load the valid copyright statements for the licenses
+//      File licenseInfo = new File(jbossSrcRoot, "thirdparty/licenses/license-info.xml");
+//      if( licenseInfo.exists() == false )
+//      {
+//         log.severe("Failed to find the thirdparty/licenses/license-info.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");
+//            // The id will be blank if there is no id attribute
+//            if( id.length() == 0 )
+//               continue;
+//            String text = getElementContent(copyright);
+//            if( text == null )
+//               continue;
+//            // Replace all duplicate whitespace and '*' with a single space
+//            text = text.replaceAll("[\\s*]+", " ");
+//            if( text.length() == 1)
+//               continue;
+//
+//            text = text.toLowerCase().trim();
+//            // Replace any copyright date0-date1,date2 with copyright ...
+//            text = text.replaceAll(COPYRIGHT_REGEX, "...");
+//            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("Updated jboss headers: " + jbossCount);
+      // Files with no headers details
+      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();
+
+      // Files with unknown headers details
+      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();
+
+      // License usage summary
+      log.info("Creating HeadersSummary.txt");
+      fw = new FileWriter("HeadersSummary.txt");
+      for (Iterator iter = licenseHeaders.entrySet().iterator(); iter.hasNext();)
+      {
+         Map.Entry entry = (Map.Entry) iter.next();
+         String key = (String) entry.getKey();
+         fw.write("+++ License type=" + key);
+         fw.write('\n');
+         List list = (List) entry.getValue();
+         Iterator jiter = list.iterator();
+         while (jiter.hasNext())
+         {
+            LicenseHeader lh = (LicenseHeader) jiter.next();
+            fw.write('\t');
+            fw.write(lh.id);
+            fw.write(", count=");
+            fw.write("" + lh.count);
+            fw.write('\n');
+         }
+      }
+      fw.close();
+   }
+
+   /**
+    * Get all non-comment content from the element.
+    *
+    * @param element
+    * @return the concatenated text/cdata content
+    */
+   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)
+         {
+            // Ignore comment nodes
+         }
+         else
+         {
+            result.append(child.getFirstChild());
+         }
+      }
+      return result.toString().trim();
+   }
+
+   /**
+    * Validate the headers of all java source files
+    *
+    * @param files
+    * @param level
+    * @throws IOException
+    */
+   static void processSourceFiles(File[] files, int level)
+         throws IOException
+   {
+      for (File f : files)
+      {
+         if (level == 0)
+            log.info("processing " + f);
+         if (f.isDirectory())
+         {
+            File[] children = f.listFiles(dotJavaFilter);
+            processSourceFiles(children, level + 1);
+         }
+         else
+         {
+            parseHeader(f);
+         }
+      }
+   }
+
+   /**
+    * Read the first comment upto the package ...; statement
+    *
+    * @param javaFile
+    */
+   static void parseHeader(File javaFile)
+         throws IOException
+   {
+      totalCount++;
+      RandomAccessFile raf = new RandomAccessFile(javaFile, "rw");
+      String line = raf.readLine();
+      StringBuffer tmp = new StringBuffer();
+      long endOfHeader = 0;
+      boolean packageOrImport = false;
+      while (line != null)
+      {
+         long nextEOH = raf.getFilePointer();
+         line = line.trim();
+         // Ignore any single line comments
+         if (line.startsWith("//"))
+         {
+            line = raf.readLine();
+            continue;
+         }
+
+         // If this is a package/import/class/interface statement break
+         if (line.startsWith("package") || line.startsWith("import")
+               || line.indexOf("class") >= 0 || line.indexOf("interface") >= 0)
+         {
+            packageOrImport = true;
+            break;
+         }
+
+         // Update the current end of header marker
+         endOfHeader = nextEOH;
+
+         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 = raf.readLine();
+      }
+      raf.close();
+
+      if (tmp.length() == 0 || !packageOrImport)
+      {
+         addDefaultHeader(javaFile);
+         return;
+      }
+
+
+      String text = tmp.toString();
+      // Replace all duplicate whitespace with a single space
+      text = text.replaceAll("[\\s*]+", " ");
+      text = text.toLowerCase().trim();
+      // Replace any copyright date0-date1,date2 with copyright ...
+      text = text.replaceAll(COPYRIGHT_REGEX, "...");
+      if (tmp.length() == 0)
+      {
+         System.out.println("adding default header for " + javaFile);
+         addDefaultHeader(javaFile);
+         return;
+      }
+      else
+      {
+
+
+         if (javaFile.toString().contains("BaseEvictionAlgorithm"))
+         {
+            System.out.println("Replacing header for " + javaFile);
+            System.out.println("Existing header: " + tmp);
+            System.out.println("Existing header: " + text);
+            System.out.println("EOH: " + endOfHeader);
+         }
+
+         replaceHeader(javaFile, endOfHeader);
+         return;
+      }
+      // Search for a matching header
+//      boolean matches = false;
+//      String matchID = null;
+//      Iterator iter = licenseHeaders.entrySet().iterator();
+//      escape:
+//      while( iter.hasNext() )
+//      {
+//         Map.Entry entry = (Map.Entry) iter.next();
+//         String key = (String) entry.getKey();
+//         System.out.println("Considering key " + key);
+//         List list = (List) entry.getValue();
+//         Iterator jiter = list.iterator();
+//         while( jiter.hasNext() )
+//         {
+//            LicenseHeader lh = (LicenseHeader) jiter.next();
+//            System.out.println("Considering hdr " + lh);
+//            if( text.startsWith(lh.text) )
+//            {
+//               matches = true;
+//               matchID = lh.id;
+//               lh.count ++;
+//               lh.usage.add(javaFile);
+//               if( log.isLoggable(Level.FINE) )
+//                  log.fine(javaFile+" matches copyright key="+key+", id="+lh.id);
+//               break escape;
+//            }
+//         }
+//      }
+//      text = null;
+//      tmp.setLength(0);
+//      if(!matches)
+//         invalidheaders.add(javaFile);
+//      else if( matchID.startsWith("jboss") && !matchID.endsWith("#0"))
+//      {
+//         // This is a legacy jboss head that needs to be updated to the default
+//         replaceHeader(javaFile, endOfHeader);
+//         jbossCount ++;
+//      }
+   }
+
+   /**
+    * Replace a legacy jboss header with the current default header
+    *
+    * @param javaFile    - the java source file
+    * @param endOfHeader - the offset to the end of the legacy header
+    * @throws IOException - thrown on failure to replace the header
+    */
+   static void replaceHeader(File javaFile, long endOfHeader)
+         throws IOException
+   {
+      if (log.isLoggable(Level.FINE))
+         log.fine("Replacing legacy jboss header in: " + javaFile);
+      RandomAccessFile raf = new RandomAccessFile(javaFile, "rw");
+      File bakFile = new File(javaFile.getAbsolutePath() + ".bak");
+      FileOutputStream fos = new FileOutputStream(bakFile);
+      fos.write(DEFAULT_HEADER.getBytes());
+      FileChannel fc = raf.getChannel();
+      long count = raf.length() - endOfHeader;
+      fc.transferTo(endOfHeader, count, fos.getChannel());
+      fc.close();
+      fos.close();
+      raf.close();
+      if (!javaFile.delete())
+         log.severe("Failed to delete java file: " + javaFile);
+      if (!bakFile.renameTo(javaFile))
+         throw new SyncFailedException("Failed to replace: " + javaFile);
+   }
+
+   /**
+    * Add the default jboss lgpl header
+    */
+   static void addDefaultHeader(File javaFile)
+         throws IOException
+   {
+      if (addDefaultHeader)
+      {
+         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);
+   }
+
+   /**
+    * A class that encapsulates the license id and valid terms header
+    */
+   static class LicenseHeader
+   {
+      String id;
+      String text;
+      int count;
+      ArrayList usage = new ArrayList();
+
+      LicenseHeader(String id, String text)
+      {
+         this.id = id;
+         this.text = text;
+      }
+   }
+
+   /**
+    * A filter which accepts files ending in .java (but not _Stub.java), or
+    * directories other than gen-src and gen-parsers
+    */
+   static class DotJavaFilter implements FileFilter
+   {
+      public boolean accept(File pathname)
+      {
+         boolean accept = false;
+         String name = pathname.getName();
+         if (pathname.isDirectory())
+         {
+            // Ignore the gen-src directories for generated output
+            accept = !name.equals("gen-src")
+                  && !name.equals("gen-parsers")
+                  && !name.equals(".svn");
+         }
+         else
+         {
+            accept = !name.endsWith("_Stub.java") && name.endsWith(".java");
+         }
+
+         return accept;
+      }
+   }
+}




More information about the jbosscache-commits mailing list