changeset 13:f73d660552bb

CODETOOLS-7901360, update for jdk, jtobserver, network properties
author afedorch
date Mon, 06 Apr 2015 13:07:41 +0300
parents df2c4155dc25
children 4027bcf80b8d
files src/classes/com/sun/tdk/jcov/JREInstr.java src/classes/com/sun/tdk/jcov/TmplGen.java src/classes/com/sun/tdk/jcov/insert/AbstractUniversalInstrumenter.java src/classes/com/sun/tdk/jcov/instrument/ClassMorph.java src/classes/com/sun/tdk/jcov/instrument/DataClass.java src/classes/com/sun/tdk/jcov/instrument/DataPackage.java src/classes/com/sun/tdk/jcov/instrument/DataRoot.java src/classes/com/sun/tdk/jcov/instrument/XmlNames.java src/classes/com/sun/tdk/jcov/instrument/reader/DataRootStAX.java src/classes/com/sun/tdk/jcov/report/ClassCoverage.java src/classes/com/sun/tdk/jcov/report/PackageCoverage.java src/classes/com/sun/tdk/jcov/report/html/CoverageReport.java src/classes/com/sun/tdk/jcov/report/html/resources/style.css src/classes/com/sun/tdk/jcov/runtime/JCovSESocketSaver.java src/classes/com/sun/tdk/jcov/runtime/NetworkSatelliteDecorator.java src/classes/com/sun/tdk/jcov/runtime/PropertyFinder.java
diffstat 16 files changed, 509 insertions(+), 76 deletions(-) [+]
line wrap: on
line diff
--- a/src/classes/com/sun/tdk/jcov/JREInstr.java	Fri Jan 16 18:45:39 2015 +0400
+++ b/src/classes/com/sun/tdk/jcov/JREInstr.java	Mon Apr 06 13:07:41 2015 +0300
@@ -29,12 +29,8 @@
 import com.sun.tdk.jcov.tools.JCovCMDTool;
 import com.sun.tdk.jcov.tools.OptionDescr;
 import com.sun.tdk.jcov.util.Utils;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStreamWriter;
+
+import java.io.*;
 import java.net.URL;
 import java.net.URLClassLoader;
 import java.nio.charset.Charset;
@@ -122,7 +118,14 @@
                 expandJimage(jimageInstr, tempDirName);
 
                 File dirtoInstrument = new File(jimageInstr.getParent(), tempDirName);
+                //still need it
                 Utils.addToClasspath(new String[]{dirtoInstrument.getAbsolutePath()});
+                for (File file:dirtoInstrument.listFiles()){
+                    if (file.isDirectory()){
+                        Utils.addToClasspath(new String[]{file.getAbsolutePath()});
+                    }
+                }
+
                 if (jimageInstr.equals(toInstrument)) {
                     instr.instrumentFile(dirtoInstrument.getAbsolutePath(), null, implant.getAbsolutePath());
                 }
@@ -178,7 +181,6 @@
             Utils.addToClasspath(srcs.toArray(new String[0]));
             instr.instrumentFiles(srcs.toArray(new String[0]), null, null);
         }
-
         instr.finishWork();
         return SUCCESS_EXIT_CODE;
     }
--- a/src/classes/com/sun/tdk/jcov/TmplGen.java	Fri Jan 16 18:45:39 2015 +0400
+++ b/src/classes/com/sun/tdk/jcov/TmplGen.java	Mon Apr 06 13:07:41 2015 +0300
@@ -34,8 +34,10 @@
 import com.sun.tdk.jcov.tools.OptionDescr;
 import com.sun.tdk.jcov.util.Utils;
 import java.io.File;
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.util.logging.Level;
+import java.util.*;
 
 /**
  * <p> Template generation. </p> <p> JCov Template file should be used to merge
@@ -58,6 +60,7 @@
     private boolean instrumentAnonymous = true;
     private boolean instrumentSynthetic = true;
     private InstrumentationOptions.InstrumentationMode mode;
+    private HashMap<String, String> moduleInfo = null;
 
     /**
      * Legacy CMD line entry poiny (use 'java -jar jcov.jar TmplGen' from cmd
@@ -97,15 +100,94 @@
         return SUCCESS_EXIT_CODE;
     }
 
+    private boolean expandJimage(File jimage, String tempDirName){
+        try {
+            String command = jimage.getParentFile().getParentFile().getParent()+File.separator+"bin"+File.separator+"jimage extract --dir "+
+                    jimage.getParent()+File.separator+tempDirName+" "+jimage.getAbsolutePath();
+            Process process = Runtime.getRuntime().exec(command);
+            process.waitFor();
+            if (process.exitValue() != 0) {
+                //logger.log(Level.SEVERE, "wrong command for expand jimage: "+command);
+                return false;
+            }
+        } catch (Exception e) {
+            //logger.log(Level.SEVERE, "exception in process(expanding jimage)", e);
+            return false;
+        }
+        return true;
+    }
+
     public void generateAndSave(String[] files) throws IOException {
         setDefaultInstrumenter();
         for (String root : files) {
-            instrumenter.instrument(new File(root), null);
+            if (root.endsWith(".jimage")){
+                File rootFile = new File(root);
+                String jimagename = getJImageName(rootFile);
+
+                expandJimage(rootFile, "temp_"+jimagename);
+                File tempJimage = new File(rootFile.getParentFile().getAbsolutePath()+File.separator+"temp_"+jimagename);
+                //still need it
+                Utils.addToClasspath(new String[]{tempJimage.getAbsolutePath()});
+                for (File file:tempJimage.listFiles()){
+                    if (file.isDirectory()){
+                        Utils.addToClasspath(new String[]{file.getAbsolutePath()});
+                    }
+                }
+                instrumenter.instrument(new File(rootFile.getParentFile().getAbsolutePath()+File.separator+"temp_"+jimagename), null);
+                File jdata = new File(rootFile.getParentFile().getAbsolutePath()+File.separator+"temp_"+jimagename+File.separator+jimagename+".jdata");
+                if (jdata.exists()){
+                   fillModuleInfo(jdata);
+                }
+            }
+            else {
+                instrumenter.instrument(new File(root), null);
+            }
+        }
+        for (String root : files) {
+            if (root.endsWith(".jimage")) {
+                File rootFile = new File(root);
+                Utils.deleteDirectory(new File(rootFile.getParentFile().getAbsolutePath() + File.separator + "temp_" + getJImageName(rootFile)));
+            }
         }
         instrumenter.finishWork();
         instrumenter = null;
     }
 
+    private String getJImageName(File jimage){
+        String jimagename = jimage.getName();
+        int pos = jimagename.lastIndexOf(".");
+        if (pos > 0) {
+            jimagename = jimagename.substring(0, pos);
+        }
+        return jimagename;
+    }
+
+    private void fillModuleInfo(File jdata){
+        try {
+            HashMap<String, String> packages = new HashMap<String, String>();
+            Scanner sc = new Scanner(jdata);
+
+            while (sc.hasNextLine()) {
+                String line = sc.nextLine();
+                String[] lineInfo = line.split("\\t");
+                for (int i = 1; i < lineInfo.length; i++){
+                    packages.put(lineInfo[i], lineInfo[0]);
+                }
+            }
+            sc.close();
+
+            if (moduleInfo == null){
+                moduleInfo  = new HashMap<String, String>();
+            }
+
+            moduleInfo.putAll(packages);
+
+        }
+        catch (FileNotFoundException e) {
+            e.printStackTrace();
+        }
+    }
+
     public void generateTemplate(String[] files) throws IOException {
         if (instrumenter == null) {
             setDefaultInstrumenter();
@@ -140,6 +222,9 @@
                 }
 
                 public void finishWork() {
+                    if (moduleInfo != null){
+                        morph.updateModuleInfo(moduleInfo);
+                    }
                     morph.saveData(template, InstrumentationOptions.MERGE.MERGE);
                 }
             };
--- a/src/classes/com/sun/tdk/jcov/insert/AbstractUniversalInstrumenter.java	Fri Jan 16 18:45:39 2015 +0400
+++ b/src/classes/com/sun/tdk/jcov/insert/AbstractUniversalInstrumenter.java	Mon Apr 06 13:07:41 2015 +0300
@@ -155,6 +155,10 @@
         boolean instredFine = true;
         int classLength = (int) f.length();
 
+        if (f.getName().equals("module-info.class")){
+            return true;
+        }
+
         ensureClassBufLength(classLength, false);
         FileInputStream fis = null;
 
--- a/src/classes/com/sun/tdk/jcov/instrument/ClassMorph.java	Fri Jan 16 18:45:39 2015 +0400
+++ b/src/classes/com/sun/tdk/jcov/instrument/ClassMorph.java	Mon Apr 06 13:07:41 2015 +0300
@@ -224,7 +224,11 @@
         }
 
         ClassWriter cw = new OverriddenClassWriter(cr, opt, loader);
-        DataClass k = new DataClass(root.rootId(), fullname, checksum, false);
+        String moduleName = getModuleName(fullname);
+        if (moduleName == null){
+            moduleName = "module no_module";
+        }
+        DataClass k = new DataClass(root.rootId(), fullname, moduleName.substring(7), checksum, false);
 //        ClassVisitor cv = shouldFlush ? new TraceClassVisitor
 //                (cw, DebugUtils.getPrintWriter(fullname, Options.getFlushPath())) :
 //                cw;
@@ -254,6 +258,23 @@
         }
     }
 
+    private String getModuleName(String fullname){
+        String result = null;
+        try{
+            if (fullname.contains("$$")){
+                fullname = fullname.substring(0, fullname.indexOf("$$"));
+            }
+            Class cls = Class.forName(fullname.replaceAll("/","."));
+            java.lang.reflect.Method method = Class.class.getDeclaredMethod("getModule", null);
+            Object module = method.invoke(cls, null);
+            result = module.toString();
+
+        }catch(Throwable t){
+
+        }
+        return result;
+    }
+
     public static long computeCheckSum(byte[] classfileBuffer) {
 //        Adler32 adler = new Adler32();
 //        adler.update(classfileBuffer, 0, classfileBuffer.length);
@@ -487,6 +508,17 @@
         return checksum;
     }
 
+    public void updateModuleInfo(HashMap<String, String> moduleInfo){
+        if (root != null){
+            for (DataPackage pack : root.getPackages()){
+                String moduleName = moduleInfo.get(pack.getName());
+                if (moduleName != null) {
+                    pack.setModuleName(moduleName);
+                }
+            }
+        }
+    }
+
     private void findAlreadyInstrumentedAndSetID() {
         try {
             if (outputFile == null) {
--- a/src/classes/com/sun/tdk/jcov/instrument/DataClass.java	Fri Jan 16 18:45:39 2015 +0400
+++ b/src/classes/com/sun/tdk/jcov/instrument/DataClass.java	Mon Apr 06 13:07:41 2015 +0300
@@ -60,6 +60,10 @@
      */
     private final String fullname;
     /**
+     * Module name of associated class
+     */
+    private String moduleName;
+    /**
      * Short name of associated class
      */
     private final String name;
@@ -122,7 +126,7 @@
      * @param checksum
      * @param differentiateClass
      */
-    public DataClass(int rootId, String fullname, long checksum, boolean differentiateClass) {
+    public DataClass(int rootId, String fullname, String moduleName, long checksum, boolean differentiateClass) {
         super(rootId);
         this.fullname = fullname;
         this.checksum = checksum;
@@ -135,6 +139,15 @@
         this.methods = new LinkedList<DataMethod>();
         this.fields = new LinkedList<DataField>();
         this.differentiateClass = differentiateClass; // is always false at the moment
+        this.moduleName = moduleName;
+      }
+
+    public String getModuleName(){
+        return moduleName;
+    }
+
+    public void setModuleName(String moduleName){
+        this.moduleName = moduleName;
     }
 
     /**
@@ -685,7 +698,7 @@
      * @return clone
      */
     public DataClass clone(int rootId) {
-        DataClass res = new DataClass(rootId, fullname, -1, differentiateClass);
+        DataClass res = new DataClass(rootId, fullname, moduleName, -1, differentiateClass);
         res.access = access;
         res.signature = signature;
         res.superName = superName;
@@ -1055,6 +1068,7 @@
     void writeObject(DataOutput out) throws IOException {
         super.writeObject(out);
         out.writeUTF(name);
+        writeString(out, moduleName);
         writeString(out, fullname);
         writeString(out, signature);
         writeString(out, source);
@@ -1096,7 +1110,9 @@
 
     DataClass(int rootID, DataInput in) throws IOException {
         super(rootID, in);
+        //moduleName = "test.java.base";
         name = in.readUTF();
+        moduleName = readString(in);
         fullname = readString(in);
         signature = readString(in);
         source = readString(in);
--- a/src/classes/com/sun/tdk/jcov/instrument/DataPackage.java	Fri Jan 16 18:45:39 2015 +0400
+++ b/src/classes/com/sun/tdk/jcov/instrument/DataPackage.java	Mon Apr 06 13:07:41 2015 +0300
@@ -48,6 +48,8 @@
      * Name of associated package
      */
     private final String name;
+
+    private String moduleName;
     /**
      * Classes in this package
      */
@@ -59,12 +61,21 @@
      * @param rootId
      * @param name Associated package name
      */
-    public DataPackage(int rootId, String name) {
+    public DataPackage(int rootId, String name, String modulename) {
         super(rootId);
         this.name = name;
+        this.moduleName = modulename;
         this.classes = new LinkedList<DataClass>();
     }
 
+    public void setModuleName(String moduleName){
+        this.moduleName = moduleName;
+    }
+
+    public String getModuleName(){
+        return moduleName;
+    }
+
     /**
      * Get associated package name
      *
@@ -142,6 +153,7 @@
     @Override
     void xmlAttrs(XmlContext ctx) {
         ctx.attr(XmlNames.NAME, name.replace('/', '.'));
+        ctx.attr(XmlNames.MODULE_NAME, moduleName);
     }
 
     /**
@@ -191,6 +203,7 @@
 
     void writeObject(DataOutput out) throws IOException {
         out.writeUTF(name);
+        out.writeUTF(moduleName);
         out.writeShort(classes.size());
         for (DataClass dc : classes) {
             dc.writeObject(out);
@@ -200,6 +213,7 @@
     DataPackage(int rootID, DataInput in) throws IOException {
         super(rootID);
         name = in.readUTF();
+        moduleName = in.readUTF();
         int classNum = in.readUnsignedShort();
         classes = new ArrayList<DataClass>(classNum);
         for (int i = 0; i < classNum; ++i) {
--- a/src/classes/com/sun/tdk/jcov/instrument/DataRoot.java	Fri Jan 16 18:45:39 2015 +0400
+++ b/src/classes/com/sun/tdk/jcov/instrument/DataRoot.java	Mon Apr 06 13:07:41 2015 +0300
@@ -398,10 +398,10 @@
      * @param name
      * @return package
      */
-    public DataPackage findPackage(String name) {
+    public DataPackage findPackage(String name, String moduleName) {
         DataPackage pack = packages.get(name);
         if (pack == null) {
-            pack = new DataPackage(rootId, name);
+            pack = new DataPackage(rootId, name, moduleName);
             packages.put(pack.getName(), pack);
         }
         return pack;
@@ -463,7 +463,7 @@
                 (slash < 0)
                 ? ""
                 : clazz.getFullname().substring(0, slash);
-        this.findPackage(pname).addClass(clazz);
+        this.findPackage(pname, clazz.getModuleName()).addClass(clazz);
     }
 
     /**
@@ -472,7 +472,7 @@
      * <code>findPackage()</code> method
      *
      * @param pack
-     * @see #findPackage(java.lang.String)
+     * @see #findPackage(java.lang.String, java.lang.String)
      */
     public void addPackage(DataPackage pack) {
         packages.put(pack.getName(), pack);
@@ -824,6 +824,9 @@
                 }
             } else {
                 DataPackage p = packages.get(pOther.getName());
+                if (p.getModuleName() == null || p.getModuleName().equals("no_module")) {
+                    p.setModuleName(pOther.getModuleName());
+                }
                 for (DataClass cl : pOther.getClasses()) {
                     DataClass c = p.findClass(cl.getName());
                     if (c == null) {
@@ -835,6 +838,7 @@
                         }
                     } else {
                         c.merge(cl);
+                        c.setModuleName(cl.getModuleName());
                     }
                 }
             }
--- a/src/classes/com/sun/tdk/jcov/instrument/XmlNames.java	Fri Jan 16 18:45:39 2015 +0400
+++ b/src/classes/com/sun/tdk/jcov/instrument/XmlNames.java	Mon Apr 06 13:07:41 2015 +0300
@@ -103,4 +103,6 @@
     public static final String CRT_LINE = "line";
     public static final String CRT_COL = "col";
     public static final String INNER_CLASS = "inner";
+
+    public static final String MODULE_NAME = "moduleName";
 }
--- a/src/classes/com/sun/tdk/jcov/instrument/reader/DataRootStAX.java	Fri Jan 16 18:45:39 2015 +0400
+++ b/src/classes/com/sun/tdk/jcov/instrument/reader/DataRootStAX.java	Mon Apr 06 13:07:41 2015 +0300
@@ -92,12 +92,13 @@
 
     private void readPackage() throws XMLStreamException, FileFormatException {
         String packName = parser.getAttributeValue(null, XmlNames.NAME);
+        String moduleName = parser.getAttributeValue(null, XmlNames.MODULE_NAME);
         int event = parser.getEventType();
         while (true) {
             event = parser.nextTag();
             switch (event) {
                 case XMLStreamConstants.START_ELEMENT:
-                    readClass(packName);
+                    readClass(packName, moduleName);
                     break;
                 case XMLStreamReader.END_ELEMENT://end of package
                     if (parser.getLocalName().equals(XmlNames.PACKAGE)) {//not necessary?!
@@ -108,12 +109,12 @@
         }
     }
 
-    private void readClass(String packName) throws FileFormatException {
+    private void readClass(String packName, String moduleName) throws FileFormatException {
         String clName = parser.getAttributeValue(null, XmlNames.NAME);
         String fullName = packName.isEmpty() ? clName
                 : packName.replaceAll("\\.", "/") + "/" + clName;
         String checksum = parser.getAttributeValue(null, XmlNames.CHECKSUM);
-        DataClass clazz = new DataClass(root.rootId(), fullName, checksum == null ? -1
+        DataClass clazz = new DataClass(root.rootId(), fullName, moduleName,checksum == null ? -1
                 : Long.parseLong(checksum), root.isDifferentiateElements());
 
         clazz.setInfo(parser.getAttributeValue(null, XmlNames.FLAGS), parser.getAttributeValue(null, XmlNames.SIGNATURE),
--- a/src/classes/com/sun/tdk/jcov/report/ClassCoverage.java	Fri Jan 16 18:45:39 2015 +0400
+++ b/src/classes/com/sun/tdk/jcov/report/ClassCoverage.java	Mon Apr 06 13:07:41 2015 +0300
@@ -67,6 +67,7 @@
     private String fullname;
     private String name;
     private String packagename;
+    private String modulename;
 
     /**
      * <p> Creates new ClassCoverage instance. </p>
@@ -88,6 +89,7 @@
         fullname = clz.getFullname();
         name = clz.getName();
         packagename = clz.getPackageName();
+        modulename = clz.getModuleName();
 
         for (DataMethod method : clz.getMethods()) {
             if (filter != null && !filter.accept(clz, method)) {
@@ -277,6 +279,10 @@
         return packagename;
     }
 
+    public String getModuleName() {
+        return modulename;
+    }
+
     /**
      * @return canonical classname
      */
--- a/src/classes/com/sun/tdk/jcov/report/PackageCoverage.java	Fri Jan 16 18:45:39 2015 +0400
+++ b/src/classes/com/sun/tdk/jcov/report/PackageCoverage.java	Mon Apr 06 13:07:41 2015 +0300
@@ -84,7 +84,7 @@
 
     private List<ClassCoverage> _getClassCoverageList(DataRoot fileImage, String srcRoots[], List<JavapClass> javapClasses, ProductCoverage.CoverageFilter filter, boolean anonym) {
         List<ClassCoverage> result = new ArrayList<ClassCoverage>();
-        DataPackage pkg = fileImage.findPackage(name);
+        DataPackage pkg = fileImage.findPackage(name, "");
         for (DataClass cls : pkg.getClasses()) {
             ClassCoverage cc = new ClassCoverage(cls, srcRoots, javapClasses, filter, anonym);
             if (filter == null || filter.accept(cc)) {
--- a/src/classes/com/sun/tdk/jcov/report/html/CoverageReport.java	Fri Jan 16 18:45:39 2015 +0400
+++ b/src/classes/com/sun/tdk/jcov/report/html/CoverageReport.java	Mon Apr 06 13:07:41 2015 +0300
@@ -24,21 +24,8 @@
  */
 package com.sun.tdk.jcov.report.html;
 
-import com.sun.tdk.jcov.instrument.DataRoot;
 import com.sun.tdk.jcov.instrument.InstrumentationOptions;
-import com.sun.tdk.jcov.report.AbstractCoverage;
-import com.sun.tdk.jcov.report.ClassCoverage;
-import com.sun.tdk.jcov.report.DataType;
-import com.sun.tdk.jcov.report.FieldCoverage;
-import com.sun.tdk.jcov.report.ItemCoverage;
-import com.sun.tdk.jcov.report.MemberCoverage;
-import com.sun.tdk.jcov.report.MethodCoverage;
-import com.sun.tdk.jcov.report.PackageCoverage;
-import com.sun.tdk.jcov.report.ProductCoverage;
-import com.sun.tdk.jcov.report.ReportGenerator;
-import com.sun.tdk.jcov.report.SmartTestService;
-import com.sun.tdk.jcov.report.SubpackageCoverage;
-import com.sun.tdk.jcov.report.Test;
+import com.sun.tdk.jcov.report.*;
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
 import java.io.File;
@@ -132,7 +119,50 @@
         generateFrameset(directory);
         generatePackageList(directory);
         generateClassList(directory);
-        generateOverview(directory);
+        HashMap<String, CoverageData[]> modules = getModulesCoverage();
+        if (modules == null || (modules.size() == 1 && "no_module".equals(modules.keySet().iterator().next()))){
+            modules = null;
+        }
+        generateOverview(directory, modules);
+        if (modules != null) {
+            generateModulesList(directory, modules);
+        }
+
+    }
+
+    private void generateModulesList(File directory, HashMap<String, CoverageData[]> modules) throws IOException{
+        List<PackageCoverage> list = coverage.getPackages();
+
+        for (String moduleName: modules.keySet()) {
+            HashMap<String, CoverageData[]> module = new HashMap<String, CoverageData[]>();
+            module.put(moduleName, modules.get(moduleName));
+            generateModuleOverview(directory, list, module);
+        }
+    }
+
+    private HashMap<String, CoverageData[]> getModulesCoverage(){
+        HashMap<String, CoverageData[]> modules = null;
+        List<PackageCoverage> list = coverage.getPackages();
+
+        if (list == null || list.size() == 0 || list.get(0) == null
+                || list.get(0).getClasses() == null || list.get(0).getClasses().get(0).getModuleName() == null){
+            return modules;
+        }
+
+        modules = new HashMap<String, CoverageData[]>();
+        for (PackageCoverage pkg : list) {
+            String moduleName = pkg.getClasses().get(0).getModuleName();
+            if (modules.get(moduleName) == null) {
+                modules.put(moduleName, new CoverageData[]{pkg.getData(DataType.CLASS), pkg.getData(DataType.METHOD),
+                        pkg.getData(DataType.BLOCK), pkg.getData(DataType.BRANCH), pkg.getData(DataType.LINE)});
+            } else {
+                CoverageData[] oldCD = modules.get(moduleName);
+                modules.put(moduleName, new CoverageData[]{oldCD[0].add(pkg.getData(DataType.CLASS)), oldCD[1].add(pkg.getData(DataType.METHOD)),
+                        oldCD[2].add(pkg.getData(DataType.BLOCK)), oldCD[3].add(pkg.getData(DataType.BRANCH)), oldCD[4].add(pkg.getData(DataType.LINE))});
+            }
+        }
+
+        return modules;
     }
 
     public void setVerbose(boolean verbose) {
@@ -248,7 +278,7 @@
 
         for (PackageCoverage pkg : list) {
             generateClassList(dir, pkg);
-            generateOverview(dir, pkg);
+            generateOverview(dir, pkg, null);
         }
     }
 
@@ -333,11 +363,134 @@
         pw.close();
     }
 
-    private void generateOverview(File dir) throws IOException {
-        generateOverview(dir, null);
+    private void generateOverview(File dir, HashMap<String, CoverageData[]> modules) throws IOException {
+        generateOverview(dir, null, modules);
     }
 
-    private void generateOverview(File dir, PackageCoverage thePackage)
+    private void generateModuleOverview(File dir, List<PackageCoverage> allPkgList, HashMap<String, CoverageData[]> module) throws IOException {
+        String filename = "overview-summary.html";
+        String rootRef = "../";
+        String moduleName = module.keySet().iterator().next();
+        if (moduleName != null) {
+            filename = moduleName
+                    + "/module-summary.html";
+            rootRef = "../";
+        } else {
+            rootRef = "";
+        }
+
+        File fsFile = new File(dir, filename);
+        if (!fsFile.getParentFile().exists()) {
+            logger.log(Level.INFO, "mkdirs:{0}", fsFile.getParentFile());
+            fsFile.getParentFile().mkdirs();
+        }
+        PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(
+                fsFile), Charset.defaultCharset())));
+        pw.println("<html>");
+        pw.println("<head>");
+        pw.println("<title>coverage report</title>");
+        pw.println("<link rel =\"stylesheet\" type=\"text/css\" href=\"" + rootRef
+                + "style.css\" title=\"Style\">");
+        pw.println("<script type=\"text/javascript\" src=\"" + rootRef
+                + "sorttable.js\"></script>");
+        pw.println("</head>");
+        pw.println("<body>");
+        pw.println("<span class=\"title\"> <b>" + title + " "
+                + /*coverage.getData(ColumnName.PRODUCT) + */ "</b> </span>");
+        pw.println("<p>");
+
+        if (module != null) {
+            generateModulesInfo(pw, module, true/*,""*/);
+        }
+
+        pw.println("</tr>");
+        pw.println("</table>");
+        pw.println("<p>");
+
+        List<PackageCoverage> modulesPkgList = new ArrayList<PackageCoverage>();
+        for (PackageCoverage pc : allPkgList){
+            if (pc.getClasses().get(0).getModuleName().equals(moduleName)){
+                modulesPkgList.add(pc);
+            }
+        }
+
+        List<PackageCoverage> pkgList = modulesPkgList;
+        List<ClassCoverage> classes = new ArrayList<ClassCoverage>();
+        for (PackageCoverage thePackage : pkgList) {
+            classes.addAll(thePackage.getClasses());
+        }
+            //PackageCoverage thePackage = pc;
+
+            SubpackageCoverage subCov = new SubpackageCoverage();
+           // if (thePackage != null) {
+
+                //pkgList = getSubPackages(thePackage);
+              //  if (pkgList.size() > 0) {
+                    //subCov.add(thePackage);
+                    pw.println("<span class=\"title2\">Packages</span><br>");
+                    pw.println("<table class=\"report\" cellpadding=\"0\" cellspacing=\"0\" id=\"subpackages\">");
+                    pw.println("<tr class=\"report\">");
+                    pw.println("<th class=\"report\">Name</th>");
+                    pw.println("<th class=\"report_number\">#classes</th>");
+                    pw.println("<th class=\"report\">%class</th>");
+                    printColumnHeaders(pw, "");
+                    //pw.println("<th class=\"report\">%total</th>");
+                    pw.println("</tr>");
+                    for (PackageCoverage pkg : pkgList) {
+                        subCov.add(pkg);
+                        pw.println("<tr class=\"report\">");
+                        String subPkgDir = "../"+pkg.getName()/*.substring(
+                                thePackage.getName().length() + 1)*/.replace('.', '/');
+                        pw
+                                .println("<td class=\"reportText\"><a href=\"" + subPkgDir
+                                        + "/package-summary.html\">" + pkg.getName()
+                                        + "</a></td>");
+                        pw.println("<td class=\"reportValue\">"
+                                + pkg.getData(DataType.CLASS).getTotal() + "</td>");
+                        pw.println("<td class=\"reportValue\">"
+                                + decorate(pkg.getCoverageString(DataType.CLASS)) + "</td>");
+                        printColumnCoverages(pw, pkg, true, "");
+                    /*pw.println("<td class=\"reportValue\">"
+                     + generatePercentResult(pkg.getTotalCoverageString()) + "</td>");*/
+                        pw.println("</tr>");
+                    }
+                    pw.println("</table>");
+                    pw.println("<p>");
+              //  }
+
+
+                logger.log(Level.INFO, "generateOverview:classes.size:{0}", classes.size());
+                if (classes.size() > 0) {
+                    pw.println("<span class=\"title2\">Classes</span><br>");
+                    pw.println("<table class=\"report\" cellpadding=\"0\" cellspacing=\"0\" id=\"classes\">");
+                    pw.println("<tr class=\"report\">");
+                    pw.println("<th class=\"report\">Name</th>");
+                    printColumnHeaders(pw, "");
+                    // pw.println("<th class=\"report\">%total</th>");
+                    pw.println("</tr>");
+                    int i = 0;
+                    for (ClassCoverage cc : classes) {
+                        logger.log(Level.INFO, "{0} generateOverview():cl:{1}", new Object[]{++i, cc.getName()});
+                        String classFilename = cc.getName();
+                        pw.println("<tr class=\"report\">");
+                        pw.println("<td class=\"reportText\"><a href=\"" +"../"+cc.getPackageName().replace('.', '/')+"/"+ classFilename
+                                + ".html\">" + classFilename + "</a></td>");
+                        printColumnCoverages(pw, cc, true, "");
+                        // pw.println("<td class=\"reportValue\">"
+                        //   + generatePercentResult(cc.getTotalCoverageString()) + "</td>");
+                        pw.println("</tr>");
+                    }
+                }
+            //}
+            pw.println("</table>");
+
+        pw.println(generateFooter());
+        pw.println("</body>");
+        pw.println("</html>");
+        pw.close();
+    }
+
+    private void generateOverview(File dir, PackageCoverage thePackage, HashMap<String, CoverageData[]> modules)
             throws IOException {
         String filename = "overview-summary.html";
         String rootRef;
@@ -371,24 +524,24 @@
         pw.println("<table class=\"report\" cellpadding=\"0\" cellspacing=\"0\">");
         pw.println("<tr class=\"report\">");
         pw.println("<th class=\"report\">&nbsp;</th>");
-        pw.println("<th class=\"report\">#classes</th>");
+        pw.println("<th class=\"report_number\">#classes</th>");
         printColumnHeaders(pw, "");
         // pw.println("<th class=\"report\">%total</th>");
         pw.println("</tr>");
         pw.println("<tr class=\"report\">");
         if (thePackage != null) {
-            pw.println("<td class=\"reportText\">" + thePackage.getName()
-                    + "</td>");
-            pw.println("<td class=\"reportValue\">"
+            pw.println("<td class=\"reportText\"> <b>" + thePackage.getName()
+                    + "</b></td>");
+            pw.println("<td class=\"reportValue_number\">"
                     + thePackage.getData(DataType.CLASS).getTotal() + "</td>");
             printColumnCoverages(pw, thePackage, false, "");
             //  pw.println("<td class=\"reportValue\">"
             //      + generatePercentResult(thePackage.getTotalCoverageString())
             //      + "</td>");
         } else {
-            pw.println("<td class=\"reportText\">"
-                    + "Overall statistics" + "</td>");
-            pw.println("<td class=\"reportValue\">"
+            pw.println("<td class=\"reportText\"> <b>"
+                    + "Overall statistics" + "</b> </td>");
+            pw.println("<td class=\"reportValue_number\">"
                     + coverage.getData(DataType.CLASS).getTotal() + "</td>");
             printColumnCoverages(pw, coverage, false, "");
             //  pw.println("<td class=\"reportValue\">"
@@ -401,14 +554,15 @@
         List<PackageCoverage> pkgList = null;
         SubpackageCoverage subCov = new SubpackageCoverage();
         if (thePackage != null) {
+            //generateModulesInfo(pw, modules, false, thePackage.getName());
             pkgList = getSubPackages(thePackage);
             if (pkgList.size() > 0) {
                 subCov.add(thePackage);
-                pw.println("<span class=\"title2\">Packages</span><br>");
+                pw.println("<span class=\"title2\">Subpackages</span><br>");
                 pw.println("<table class=\"report\" cellpadding=\"0\" cellspacing=\"0\" id=\"subpackages\">");
                 pw.println("<tr class=\"report\">");
                 pw.println("<th class=\"report\">Name</th>");
-                pw.println("<th class=\"report\">#classes</th>");
+                pw.println("<th class=\"report_number\">#classes</th>");
                 pw.println("<th class=\"report\">%class</th>");
                 printColumnHeaders(pw, "");
                 //pw.println("<th class=\"report\">%total</th>");
@@ -422,7 +576,7 @@
                             .println("<td class=\"reportText\"><a href=\"" + subPkgDir
                             + "/package-summary.html\">" + pkg.getName()
                             + "</a></td>");
-                    pw.println("<td class=\"reportValue\">"
+                    pw.println("<td class=\"reportValue_number\">"
                             + pkg.getData(DataType.CLASS).getTotal() + "</td>");
                     pw.println("<td class=\"reportValue\">"
                             + decorate(pkg.getCoverageString(DataType.CLASS)) + "</td>");
@@ -461,11 +615,14 @@
         } else {
             pkgList = coverage.getPackages();
             if (pkgList.size() > 0) {
+                if (modules != null) {
+                    generateModulesInfo(pw, modules, false);
+                }
                 pw.println("<span class=\"title2\">Packages</span><br>");
                 pw.println("<table class=\"report\" cellpadding=\"0\" cellspacing=\"0\" id=\"packages\">");
                 pw.println("<tr class=\"report\">");
                 pw.println("<th class=\"report\">Name</th>");
-                pw.println("<th class=\"report\">#classes</th>");
+                pw.println("<th class=\"report_number\">#classes</th>");
                 printColumnHeaders(pw, "");
                 // pw.println("<th class=\"report\">%total</th>");
                 pw.println("</tr>");
@@ -476,7 +633,7 @@
                             + pkg.getName().replace('.', '/')
                             + "/package-summary.html\">" + pkg.getName()
                             + "</a></td>");
-                    pw.println("<td class=\"reportValue\">"
+                    pw.println("<td class=\"reportValue_number\">"
                             + pkg.getData(DataType.CLASS).getTotal() + "</td>");
                     printColumnCoverages(pw, pkg, true, "");
                     //  pw.println("<td class=\"reportValue\">"
@@ -493,13 +650,13 @@
             pw.println("<table class=\"report\" cellpadding=\"0\" cellspacing=\"0\" id=\"subpackages\">");
             pw.println("<tr class=\"report\">");
             pw.println("<th class=\"report\">-</th>");
-            pw.println("<th class=\"report\">#classes</th>");
+            pw.println("<th class=\"report_number\">#classes</th>");
             //pw.println("<th class=\"report\">%total</th>");
             printColumnHeaders(pw, "");
             pw.println("</tr>");
             pw.println("<tr class=\"report\">");
             pw.println("<td class=\"reportValue\"></td>");
-            pw.println("<td class=\"reportValue\">"
+            pw.println("<td class=\"reportValue_number\">"
                     + subCov.getData(DataType.CLASS).getTotal() + "</td>");
             //pw.println("<td class=\"reportValue\">"
             //    + decorate(subCov.getClassCoverageString()) + "</td>");
@@ -515,6 +672,53 @@
         pw.close();
     }
 
+    private void generateModulesInfo(PrintWriter pw, HashMap<String, CoverageData[]> modules, boolean decorate){
+
+        if (modules.keySet().size() > 1) {
+            pw.println("<span class=\"title2\">Modules</span><br>");
+        }
+        else{
+            pw.println("<span class=\"title2\">Module</span><br>");
+        }
+        pw.println("<table class=\"report\" cellpadding=\"0\" cellspacing=\"0\" id=\"modules\">");
+        pw.println("<tr class=\"report\">");
+        pw.println("<th class=\"report\">Name</th>");
+        pw.println("<th class=\"report_number\">#classes</th>");
+        printColumnHeaders(pw, "");
+        pw.println("</tr>");
+
+        for (String module : modules.keySet()) {
+            pw.println("<tr class=\"report\">");
+            if (!decorate) {
+                pw.println("<td class=\"reportText\"><a href=\""
+                        + module
+                        + "/module-summary.html\">" + module
+                        + "</a></td>");
+            }
+            else{
+                pw.println("<td class=\"reportText\"> <b>" + module
+                        + " </b> </a></td>");
+            }
+
+            pw.println("<td class=\"reportValue_number\">"
+                    + modules.get(module)[0].getTotal() + "</td>");
+            for (int i = 1; i< modules.get(module).length; i++) {
+                CoverageData cd = modules.get(module)[i];
+                if (!decorate) {
+                    pw.println("<td class=\"reportValue\">"
+                            + decorate(cd.getFormattedCoverage()) + "</td>");
+                }
+                else{
+                    pw.println("<td class=\"reportValue\">"
+                            +generatePercentResult(cd.getFormattedCoverage()) + "</td>");
+                }
+            }
+            pw.println("</tr>");
+        }
+        pw.println("</table>");
+        pw.println("<p>");
+    }
+
     enum columns {
 
         method, field, block, branch, line
@@ -736,8 +940,8 @@
         // pw.println(" <th class=\"report\">%total</th>");
         pw.println(" </tr>");
         pw.println(" <tr class=\"report\">");
-        pw.println(" <td class=\"reportText\"><span class=\"text\">"
-                + theClass.getFullClassName() + "</span></td>");
+        pw.println(" <td class=\"reportText\"><span class=\"text\"> <b>"
+                + theClass.getFullClassName() + "</b></span></td>");
 
         printColumnCoverages(pw, theClass, false, " ");
         //  pw.println(" <td class=\"reportValue\">"
@@ -1260,11 +1464,12 @@
             badNumber = true;
         }
         StringBuilder sb = new StringBuilder();
-        sb.append("<table class=\"percentGraph\" cellpadding=\"0\" cellspacing=\"0\" align=\"right\">");
+        sb.append("<table cellpadding=\"0\" cellspacing=\"0\" align=\"center\">");
         sb.append("<tr>");
         // sb.append("<td><span class=\"text\">" + decorate(percentValue)
         sb.append("<td><span class=\"text\"><b>").append(value.trim()).append("</b>%").append(cov_total.trim()).append("</span></td>");
         if (!badNumber) {
+            sb.append("<tr>");
             sb.append("<td>");
             sb.append("<table class=\"percentGraph\" cellpadding=\"0\" cellspacing=\"0\">");
             sb.append("<tr>");
@@ -1273,6 +1478,7 @@
             sb.append("</tr>");
             sb.append("</table>");
             sb.append("</td>");
+            sb.append("</tr>");
         }
         sb.append("</tr>");
         sb.append("</table>");
@@ -1292,10 +1498,20 @@
         int idx = coverageString.indexOf("%");
         if (idx != -1) {
             StringBuilder sb = new StringBuilder();
-            sb.append("<b>");
-            sb.append(coverageString.substring(0, idx));
-            sb.append("</b>");
-            sb.append(coverageString.substring(idx));
+            sb.append("<table class=\"report\">");
+                sb.append("<tr>");
+                sb.append("<td class=\"coverage_left\">");
+                    sb.append("<span class=\"text_bold\">");
+                        sb.append(coverageString.substring(0, idx+1).trim());
+                    sb.append("</span>");
+                sb.append("</td>");
+                sb.append("<td class=\"coverage_right\"> ");
+                    sb.append("<span class=\"text\">");
+                        sb.append(coverageString.substring(idx+1).trim());
+                    sb.append("</span>");
+                sb.append("</td>");
+                sb.append("</tr>");
+            sb.append("</table>");
             return sb.toString();
         }
         return coverageString;
--- a/src/classes/com/sun/tdk/jcov/report/html/resources/style.css	Fri Jan 16 18:45:39 2015 +0400
+++ b/src/classes/com/sun/tdk/jcov/report/html/resources/style.css	Mon Apr 06 13:07:41 2015 +0300
@@ -47,6 +47,16 @@
 
 tr.report {
 	border: #dcdcdc 1px solid;
+    width: 13%;
+}
+
+tr.report_number {
+    border: #dcdcdc 1px solid;
+    width: 6%;
+}
+
+tr.report:hover {
+    background: #fbfbfb;
 }
 
 table.percentGraph {
@@ -62,6 +72,15 @@
 	cursor:			default;
 }
 
+th.report_number{
+    background: #F0F0F0;
+    font-size: inherit !important;
+    font-weight: bold;
+    border: #dcdcdc 1px solid;
+    cursor:			default;
+    width: 6%;
+}
+
 
 th.report:hover {
     background: #dcdcdc;
@@ -88,37 +107,45 @@
 td.reportValue {
 	font-size: inherit !important;
 	border: #dcdcdc 1px solid;
-	text-align: right;
+	text-align: center;
+    width: 13%;
+}
+
+td.reportValue_number {
+    font-size: inherit !important;
+    border: #dcdcdc 1px solid;
+    text-align: center;
+    width: 6%;
 }
 
 td.reportValue_covered {
 	font-size: inherit !important;
 	border: #dcdcdc 1px solid;
 	text-align: right;
-    background: #80ff80;
+    background: #73FF95;
 }
 
 td.reportValue_uncovered {
 	font-size: inherit !important;
 	border: #dcdcdc 1px solid;
 	text-align: right;
-    background: #FF3030;
+    background: #FF4652;
 }
 
 td.spacer {
-	border-left: #FF0000 0px none;
-	border-right: #FF0000 0px none;
+	border-left: #FF4652 0px none;
+	border-right: #FF4652 0px none;
 	height: 30px;
 	padding-top: 15px;
 }
 
 td.percentCovered {
-    background: #00FF00;
+    background: #73FF95;
 	empty-cells: show;
 }
 
 td.percentUnCovered {
-    background: #FF0000;
+    background: #FF4652;
 	empty-cells: show;
 }
 
@@ -130,14 +157,14 @@
 }
 
 td.numLineCover {
-    background: #80ff80;
+    background: #73FF95;
     border-right: #dcdcdc 1px solid;
     padding-right: 3px;
     text-align: right;
 }
 
 td.numLineUnCover {
-    background: #FF3030;
+    background: #FF4652;
     border-right: #dcdcdc 1px solid;
     padding-right: 3px;
     text-align: right;
@@ -151,14 +178,14 @@
 }
 
 td.nbHitsCovered {
-    background: #80ff80;
+    background: #73FF95;
     border-right: #dcdcdc 1px solid;
     padding-right: 3px;
     text-align: left;
 }
 
 td.nbHitsUncovered {
-    background: #FF3030;
+    background: #FF4652;
     border-right: #dcdcdc 1px solid;
     padding-right: 3px;
     text-align: left;
@@ -168,6 +195,20 @@
     width: 100%;
 }
 
+td.coverage_left{
+    width : 30%;
+    text-align: right;
+    padding-bottom: 3px;
+    padding-top: 3px;
+}
+
+td.coverage_right{
+    width : 70%;
+    text-align: right;
+    padding-bottom: 3px;
+    padding-top: 3px;
+    padding-right: 3px;
+}
 pre.src {
     background: #ffffff;
     margin-top: 0px;
@@ -175,7 +216,7 @@
 }
 
 span.srcUncovered {
-    background: #FF3030;
+    background: #FF4652;
     border-right: #dcdcdc 1px solid;
     padding-right: 3px;
     text-align: right;
@@ -206,6 +247,10 @@
 span.text {
 	font-size: 12px;
 }
+span.text_bold {
+    font-size: 12px;
+    font-weight: bold;
+}
 
 span.text_italic {
 	font-size: 12px;
--- a/src/classes/com/sun/tdk/jcov/runtime/JCovSESocketSaver.java	Fri Jan 16 18:45:39 2015 +0400
+++ b/src/classes/com/sun/tdk/jcov/runtime/JCovSESocketSaver.java	Mon Apr 06 13:07:41 2015 +0300
@@ -48,7 +48,10 @@
         String urlString = "";
         try {
             urlString = ClassLoader.getSystemClassLoader().getResource(JCovSESocketSaver.class.getCanonicalName().replaceAll("\\.", "/") + ".class").toString();
-            urlString = urlString.substring(urlString.indexOf("file:"), urlString.indexOf('!'));
+            if (urlString.contains("file:") && urlString.contains("!")) {
+                urlString = urlString.substring(urlString.indexOf("file:"), urlString.indexOf('!'));
+            }
+            urlString = urlString.replaceAll("jrt:", "file:");
             URL url = new URL(urlString);
             file = new File(url.toURI());
         } catch (Exception e) {
--- a/src/classes/com/sun/tdk/jcov/runtime/NetworkSatelliteDecorator.java	Fri Jan 16 18:45:39 2015 +0400
+++ b/src/classes/com/sun/tdk/jcov/runtime/NetworkSatelliteDecorator.java	Mon Apr 06 13:07:41 2015 +0300
@@ -68,7 +68,8 @@
                         } catch (Exception e) {
                             lock.lock();
                             try {
-                                wrapped.saveResults();
+                                Collect.saveResults();
+                                //wrapped.saveResults();
                             }
                             finally {
                                 lock.unlock();
@@ -86,7 +87,8 @@
 
                                 lock.lock();
                                 try {
-                                    wrapped.saveResults();
+                                    Collect.saveResults();
+                                    //wrapped.saveResults();
                                 }
                                 finally {
                                     lock.unlock();
--- a/src/classes/com/sun/tdk/jcov/runtime/PropertyFinder.java	Fri Jan 16 18:45:39 2015 +0400
+++ b/src/classes/com/sun/tdk/jcov/runtime/PropertyFinder.java	Mon Apr 06 13:07:41 2015 +0300
@@ -542,6 +542,7 @@
      * properties
      */
     public static boolean isVMReady() {
-        return System.out != null && Runtime.getRuntime() != null && sun.misc.VM.isBooted();
+
+        return System.out != null && Runtime.getRuntime() != null;//&& sun.misc.VM.isBooted();
     }
 }
\ No newline at end of file