/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.netbeans.core.validation;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.net.URL;
import java.net.URLConnection;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.Properties;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.jar.Manifest;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.Action;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.netbeans.core.startup.layers.LayerCacheManager;
import org.netbeans.junit.NbModuleSuite;
import org.netbeans.junit.NbTestCase;
import org.netbeans.junit.Log;
import org.netbeans.junit.RandomlyFails;
import org.openide.cookies.InstanceCookie;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileSystem;
import org.openide.filesystems.FileUtil;
import org.openide.filesystems.MultiFileSystem;
import org.openide.filesystems.XMLFileSystem;
import org.openide.loaders.DataFolder;
import org.openide.loaders.DataObject;
import org.openide.loaders.DataShadow;
import org.openide.modules.Dependency;
import org.openide.util.Enumerations;
import org.openide.util.Lookup;
import org.openide.util.Mutex;
import org.openide.util.NbCollections;

/** Checks consistency of System File System contents.
 */
public class ValidateLayerConsistencyTest extends NbTestCase {

    static {
        System.setProperty("java.awt.headless", "true");
//        System.setProperty("org.openide.util.lookup.level", "FINE");
    }

    private static final String SFS_LB = "SystemFileSystem.localizingBundle";

    private ClassLoader contextClassLoader;   
    
    public ValidateLayerConsistencyTest(String name) {
        super (name);
    }
    
    public @Override void setUp() throws Exception {
        clearWorkDir();
        Mutex.EVENT.readAccess(new Mutex.Action<Void>() {
            public @Override Void run() {
                contextClassLoader = Thread.currentThread().getContextClassLoader();
                Thread.currentThread().setContextClassLoader(Lookup.getDefault().lookup(ClassLoader.class));
                return null;
            }
        });
    }
    
    public @Override void tearDown() {
        Mutex.EVENT.readAccess(new Mutex.Action<Void>() {
            public @Override Void run() {
                Thread.currentThread().setContextClassLoader(contextClassLoader);
                return null;
            }
        });
    }
    
    protected @Override boolean runInEQ() {
        return true;
    }

    public static Test suite() {
        TestSuite suite = new TestSuite();
        suite.addTest(NbModuleSuite.createConfiguration(ValidateLayerConsistencyTest.class).
                clusters("(?!ergonomics).*").enableClasspathModules(false).enableModules(".*").gui(false).suite());
        suite.addTest(NbModuleSuite.createConfiguration(ValidateLayerConsistencyTest.class).
                clusters("platform|ide").enableClasspathModules(false).enableModules(".*").gui(false).suite());
        return suite;
    }
    
    private List<String> failures = new ArrayList<>();
    
    private String appendFailure(String message,  Collection<String> warnings) {
        if (warnings.isEmpty()) {
            return null;
        }
        StringBuilder b = new StringBuilder(message);
        for (String warning : new TreeSet<String>(warnings)) {
            b.append('\n').append(warning);
        }
        String s = b.toString();
        failures.add(s);
        return s;
    }
    
    private void assertNoFailures() {
        if (failures.isEmpty()) {
            return;
        }
        fail(String.join("", failures));
    }

    private void assertNoErrors(String message, Collection<String> warnings) {
        String s = appendFailure(message, warnings);
        if (s == null) {
            return;
        }
        fail(s);
    }

    /* Causes mysterious failure in otherwise OK-looking UI/Runtime/org-netbeans-modules-db-explorer-nodes-RootNode.instance: 
    @Override
    protected Level logLevel() {
        return Level.FINER;
    }
    */

    /** whether an attribute will be handled in testInstantiateAllInstances anyway */
    private static boolean isInstanceAttribute(String attributeName) {
        if (attributeName.equals("instanceCreate")) {
            return true;
        }
        if (attributeName.equals("component")) {
            return true; // probably being used by TopComponent.openAction
        }
        return false;
    }
    
    public void testAreAttributesFine () {
        List<String> errors = new ArrayList<String>();
        
        FileObject root = FileUtil.getConfigRoot();
        Enumeration<? extends FileObject> files = Enumerations.concat(Enumerations.singleton(root), root.getChildren(true));
        while (files.hasMoreElements()) {
            FileObject fo = files.nextElement();
            
            if (
                "Keymaps/NetBeans/D-BACK_QUOTE.shadow".equals(fo.getPath()) ||
                "Keymaps/NetBeans55/D-BACK_QUOTE.shadow".equals(fo.getPath()) ||
                "Keymaps/Emacs/D-BACK_QUOTE.shadow".equals(fo.getPath())
            ) {
                // #46753
                continue;
            }
            if (
                "Services/Browsers/FirefoxBrowser.settings".equals(fo.getPath()) ||
                "Services/Browsers/MozillaBrowser.settings".equals(fo.getPath()) ||
                "Services/Browsers/NetscapeBrowser.settings".equals(fo.getPath())
            ) {
                // #161784
                continue;
            }
            
            Enumeration<String> attrs = fo.getAttributes();
            while (attrs.hasMoreElements()) {
                String name = attrs.nextElement();

                if (isInstanceAttribute(name)) {
                    continue;
                }
                
                if (name.indexOf('\\') != -1) {
                    errors.add("File: " + fo.getPath() + " attribute name must not contain backslashes: " + name);
                }
                
                Object attr = fo.getAttribute(name);
                if (attr == null) {
                    CharSequence warning = Log.enable("", Level.WARNING);
                    if (
                        fo.getAttribute("class:" + name) != null &&
                        fo.getAttribute(name) == null &&
                        warning.length() == 0
                    ) {
                        // ok, factory method returned null
                        continue;
                    }

                    errors.add("File: " + fo.getPath() + " attribute name: " + name);
                }

                if (attr instanceof URL) {
                    URL u = (URL) attr;
                    int read = -1;
                    try {
                        read = u.openStream().read(new byte[4096]);
                    } catch (IOException ex) {
                        errors.add(fo.getPath() + ": " + ex.getMessage());
                    }
                    if (read <= 0) {
                        errors.add("URL resource does not exist: " + fo.getPath() + " attr: " + name + " value: " + attr);
                    }
                }

            }
        }
        
        assertNoErrors("Some attributes in files are unreadable", errors);
    }
    
    public void testValidShadows () {
        // might be better to move into editor/options tests as it is valid only if there are options
        List<String> errors = new ArrayList<String>();
        
        FileObject root = FileUtil.getConfigRoot();
        
        Enumeration<? extends FileObject> en = root.getChildren(true);
        int cnt = 0;
        while (en.hasMoreElements()) {
            FileObject fo = en.nextElement();
            cnt++;
            
            // XXX #16761 Removing attr in MFO causes storing special-null value even in unneeded cases.
            // When the issue is fixed remove this hack.
            if("Windows2/Modes/debugger".equals(fo.getPath()) // NOI18N
            || "Windows2/Modes/explorer".equals(fo.getPath())) { // NOI18N
                continue;
            }
            
            if (
                "Keymaps/NetBeans/D-BACK_QUOTE.shadow".equals(fo.getPath()) ||
                "Keymaps/NetBeans55/D-BACK_QUOTE.shadow".equals(fo.getPath()) ||
                "Keymaps/Emacs/D-BACK_QUOTE.shadow".equals(fo.getPath())
            ) {
                // #46753
                continue;
            }
            
            try {
                DataObject obj = DataObject.find (fo);
                DataShadow ds = obj.getLookup().lookup(DataShadow.class);
                if (ds != null) {
                    Object o = ds.getOriginal();
                    if (o == null) {
                        errors.add("File " + fo + " has no original.");
                    }
                }
                else if ("shadow".equals(fo.getExt())) {
                    errors.add("File " + fo + " is not a valid DataShadow.");
                }
            } catch (Exception ex) {
                ex.printStackTrace();
                errors.add ("File " + fo + " threw " + ex);
            }
        }
        
        assertNoErrors("Some shadow files in NetBeans profile are broken", errors);
        
        if (ValidateLayerConsistencyTest.class.getClassLoader() == ClassLoader.getSystemClassLoader()) {
            // do not check the count as this probably means we are running
            // plain Unit test and not inside the IDE mode
            return;
        }
        
        
        if (cnt == 0) {
            fail("No file objects on system file system!");
        }
    }
    
    @RandomlyFails
    public void testContentCanBeRead () {
        List<String> errors = new ArrayList<String>();
        byte[] buffer = new byte[4096];
        
        Enumeration<? extends FileObject> files = FileUtil.getConfigRoot().getChildren(true);
        while (files.hasMoreElements()) {
            FileObject fo = files.nextElement();
            
            if (!fo.isData ()) {
                continue;
            }
            long size = fo.getSize();
            
            try {
                long read = 0;
                InputStream is = fo.getInputStream();
                try {
                    for (;;) {
                        int len = is.read (buffer);
                        if (len == -1) {
                            break;
                        }
                        read += len;
                    }
                } finally {
                    is.close ();
                }
                
                if (size != -1) {
                    assertEquals ("The amount of data in stream is the same as the length", size, read);
                }
                
            } catch (IOException ex) {
                ex.printStackTrace();
                errors.add ("File " + fo + " cannot be read: " + ex);
            }
        }
        
        assertNoErrors("Some files are unreadable", errors);
    }
    
    public void testInstantiateAllInstances () {
        List<String> errors = new ArrayList<String>();
        
        Enumeration<? extends FileObject> files = FileUtil.getConfigRoot().getChildren(true);
        while (files.hasMoreElements()) {
            FileObject fo = files.nextElement();
            
            if (skipFile(fo)) {
                continue;
            }
            
            try {
                DataObject obj = DataObject.find (fo);
                InstanceCookie ic = obj.getLookup().lookup(InstanceCookie.class);
                if (ic != null) {
                    Object o = ic.instanceCreate ();
                    if (fo.getPath().matches("Services/.+[.]instance")) {
                        String instanceOf = (String) fo.getAttribute("instanceOf");
                        if (instanceOf == null) {
                            errors.add("File " + fo.getPath() + " should declare instanceOf");
                        } else if (o != null) {
                            for (String piece : instanceOf.split(", ?")) {
                                if (!Class.forName(piece, true, Lookup.getDefault().lookup(ClassLoader.class)).isInstance(o)) {
                                    errors.add("File " + fo.getPath() + " claims to be a " + piece + " but is not (instance of " + o.getClass() + ")");
                                }
                            }
                        }
                    } else if (fo.getPath().matches("Services/.+[.]settings")) {
                        if (!fo.asText().contains("<instanceof")) {
                            errors.add("File " + fo.getPath() + " should declare <instanceof class=\"...\"/>");
                        }
                        // XXX test assignability here too, perhaps (but only used in legacy code)
                    }
                }
            } catch (Exception ex) {
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                PrintStream ps = new PrintStream(baos);
                ex.printStackTrace(ps);
                ps.flush();
                errors.add(
                    "File " + fo.getPath() +
                    "\nRead from: " + Arrays.toString((Object[])fo.getAttribute("layers")) +
                    "\nthrew: " + baos);
            }
        }
        
        assertNoErrors("Some instances cannot be created", errors);
    }

    public void testActionInstancesOnlyInActionsFolder() {
        List<String> errors = new ArrayList<String>();

        Enumeration<? extends FileObject> files = FileUtil.getConfigRoot().getChildren(true);
        FILE: while (files.hasMoreElements()) {
            FileObject fo = files.nextElement();

            if (skipFile(fo)) {
                continue;
            }

            try {
                DataObject obj = DataObject.find (fo);
                InstanceCookie ic = obj.getLookup().lookup(InstanceCookie.class);
                if (ic == null) {
                    continue;
                }
                Object o;
                try {
                    o = ic.instanceCreate();
                } catch (ClassNotFoundException ok) {
                    // wrong instances are catched by another test
                    continue;
                }
                if (!(o instanceof Action)) {
                    continue;
                }
                if (fo.hasExt("xml")) {
                    continue;
                }
                if (fo.getPath().startsWith("Actions/")) {
                    continue;
                }
                if (fo.getPath().startsWith("Editors/")) {
                    // editor is a bit different world
                    continue;
                }
                if (fo.getPath().startsWith("Databases/Explorer/")) {
                    // db explorer actions shall not influence start
                    // => let them be for now.
                    continue;
                }
                if (fo.getPath().startsWith("WelcomePage/")) {
                    // welcome screen actions are not intended for end user
                    continue;
                }
                if (fo.getPath().startsWith("Projects/org-netbeans-modules-mobility-project/Actions/")) {
                    // I am not sure what mobility is doing, but
                    // I guess I do not need to care
                    continue;
                }
                if (fo.getPath().startsWith("NativeProjects/Actions/")) {
                    // XXX should perhaps be replaced
                    continue;
                }
                if (fo.getPath().startsWith("contextmenu/uml/")) {
                    // UML is not the most important thing to fix
                    continue;
                }
                if (fo.getPath().equals("Menu/Help/org-netbeans-modules-j2ee-blueprints-ShowBluePrintsAction.instance")) {
                    // action included in some binary blob
                    continue;
                }
                if (Boolean.TRUE.equals(fo.getAttribute("misplaced.action.allowed"))) {
                    // it seems necessary some actions to stay outside
                    // of the Actions folder
                    continue;
                }
                if (fo.hasExt("shadow")) {
                    o = fo.getAttribute("originalFile");
                    if (o instanceof String) {
                        String origF = o.toString().replaceFirst("\\/*", "");
                        if (origF.startsWith("Actions/")) {
                            continue;
                        }
                        if (origF.startsWith("Editors/")) {
                            continue;
                        }
                    }
                }
                errors.add("File " + fo.getPath() + " represents an action which is not in Actions/ subfolder. Provided by " + Arrays.toString((Object[])fo.getAttribute("layers")));
            } catch (Exception ex) {
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                PrintStream ps = new PrintStream(baos);
                ex.printStackTrace(ps);
                ps.flush();
                errors.add ("File " + fo.getPath() + " threw: " + baos);
            }
        }

        assertNoErrors(errors.size() + " actions is not registered properly", errors);
    }
    
    public void testLayerOverrides() throws Exception {
        ClassLoader l = Lookup.getDefault().lookup(ClassLoader.class);
        assertNotNull ("In the IDE mode, there always should be a classloader", l);
        
        class ContentAndAttrs {
            final byte[] contents;
            final Map<String,Object> attrs;
            private final URL layerURL;
            ContentAndAttrs(byte[] contents, Map<String,Object> attrs, URL layerURL) {
                this.contents = contents;
                this.attrs = attrs;
                this.layerURL = layerURL;
            }
            public @Override String toString() {
                return "ContentAndAttrs[contents=" + Arrays.toString(contents) + ",attrs=" + attrs + ";from=" + layerURL + "]";
            }
            public @Override int hashCode() {
                return Arrays.hashCode(contents) ^ attrs.hashCode();
            }
            public @Override boolean equals(Object o) {
                if (!(o instanceof ContentAndAttrs)) {
                    return false;
                }
                ContentAndAttrs caa = (ContentAndAttrs) o;
                return Arrays.equals(contents, caa.contents) && attrs.equals(caa.attrs);
            }
        }
        Map</* path */String,Map</* owner */String,ContentAndAttrs>> files = new TreeMap<String,Map<String,ContentAndAttrs>>();
        Map</* path */String,Map</* attr name */String,Map</* module name */String,/* attr value */Object>>> folderAttributes =
                new TreeMap<String,Map<String,Map<String,Object>>>();
        Map<String,Set<String>> directDeps = new HashMap<String,Set<String>>();
        StringBuffer sb = new StringBuffer();
        Map<String,URL> hiddenFiles = new HashMap<String, URL>();
        Set<String> allFiles = new HashSet<String>();
        final String suffix = "_hidden";

        Enumeration<URL> en = l.getResources("META-INF/MANIFEST.MF");
        while (en.hasMoreElements ()) {
            URL u = en.nextElement();
            InputStream is = u.openStream();
            Manifest mf;
            try {
                mf = new Manifest(is);
            } finally {
                is.close();
            }
            String module = mf.getMainAttributes ().getValue ("OpenIDE-Module");
            if (module == null) {
                continue;
            }
            String depsS = mf.getMainAttributes().getValue("OpenIDE-Module-Module-Dependencies");
            if (depsS != null) {
                Set<String> deps = new HashSet<String>();
                for (Dependency d : Dependency.create(Dependency.TYPE_MODULE, depsS)) {
                    deps.add(d.getName().replaceFirst("/.+$", ""));
                }
                directDeps.put(module, deps);
            }
            for (boolean generated : new boolean[] {false, true}) {
                String layer;
                if (generated) {
                    layer = "META-INF/generated-layer.xml";
                } else {
                    layer = mf.getMainAttributes ().getValue ("OpenIDE-Module-Layer");
                    if (layer == null) {
                        continue;
                    }
                }

                URL base = new URL(u, "../");
                URL layerURL = new URL(base, layer);
                URLConnection connect;
                try {
                    connect = layerURL.openConnection();
                    connect.connect();
                } catch (FileNotFoundException x) {
                    if (generated) {
                        continue;
                    } else {
                        throw x;
                    }
                }
                connect.setDefaultUseCaches (false);
                FileSystem fs = new XMLFileSystem(layerURL);

                Enumeration<? extends FileObject> all = fs.getRoot().getChildren(true);
                while (all.hasMoreElements ()) {
                    FileObject fo = all.nextElement ();
                    String simplePath = fo.getPath();

                    if (simplePath.endsWith(suffix)) {
                        hiddenFiles.put(simplePath, layerURL);
                    } else {
                        allFiles.add(simplePath);
                    }

                    Number weight = (Number) fo.getAttribute("weight");
                    // XXX if weight != null, test that it is actually overriding something or being overridden
                    String weightedPath = weight == null ? simplePath : simplePath + "#" + weight;

                    Map<String,Object> attributes = getAttributes(fo, base);

                    if (fo.isFolder()) {
                        for (Map.Entry<String,Object> attr : attributes.entrySet()) {
                            Map<String,Map<String,Object>> m1 = folderAttributes.get(weightedPath);
                            if (m1 == null) {
                                m1 = new TreeMap<String,Map<String,Object>>();
                                folderAttributes.put(weightedPath, m1);
                            }
                            Map<String,Object> m2 = m1.get(attr.getKey());
                            if (m2 == null) {
                                m2 = new TreeMap<String,Object>();
                                m1.put(attr.getKey(), m2);
                            }
                            m2.put(module, attr.getValue());
                        }
                        continue;
                    }

                    Map<String,ContentAndAttrs> overrides = files.get(weightedPath);
                    if (overrides == null) {
                        overrides = new TreeMap<String,ContentAndAttrs>();
                        files.put(weightedPath, overrides);
                    }
                    try {
                        overrides.put(module, new ContentAndAttrs(fo.asBytes(), attributes, layerURL));
                    } catch (IOException ex) {
                        // will be reported by a different test
                    }
                }
                // make sure the filesystem closes the stream
                connect.getInputStream ().close ();
            }
        }
        assertFalse("At least one layer file is usually used", allFiles.isEmpty());

        for (Map.Entry<String,Map<String,ContentAndAttrs>> e : files.entrySet()) {
            Map<String,ContentAndAttrs> overrides = e.getValue();
            if (overrides.size() == 1) {
                continue;
            }
            Set<String> overriders = overrides.keySet();
            String file = e.getKey();

            if (new HashSet<ContentAndAttrs>(overrides.values()).size() == 1) {
                // All the same. Check whether these are parallel declarations (e.g. CND debugger vs. Java debugger), or vertical.
                for (String overrider : overriders) {
                    Set<String> deps = new HashSet<String>(directDeps.get(overrider));
                    deps.retainAll(overriders);
                    if (!deps.isEmpty()) {
                        sb.append(file).append(" is pointlessly overridden in ").append(overrider).
                                append(" relative to ").append(deps.iterator().next()).append('\n');
                    }
                }
                continue;
            }

            sb.append(file).append(" is provided by: ").append(overriders).append('\n');
            for (Map.Entry<String,ContentAndAttrs> entry : overrides.entrySet()) {
                ContentAndAttrs contentAttrs = entry.getValue();
                sb.append(" ").append(entry.getKey()).append(": content = '").append(new String(contentAttrs.contents)).
                        append("', attributes = ").append(contentAttrs.attrs).append("\n");
            }
        }        
        
        for (Map.Entry<String,Map<String,Map<String,Object>>> entry1 : folderAttributes.entrySet()) {
            for (Map.Entry<String,Map<String,Object>> entry2 : entry1.getValue().entrySet()) {
                if (new HashSet<Object>(entry2.getValue().values()).size() > 1) {
                    sb.append("Some modules conflict on the definition of ").append(entry2.getKey()).append(" for ").
                            append(entry1.getKey()).append(": ").append(entry2.getValue()).append("\n");
                }
            }
        }

        if (sb.length () > 0) {
            fail("Some modules override some files without using the weight attribute correctly\n" + sb);
        }


        for (Map.Entry<String, URL> e : hiddenFiles.entrySet()) {
            String p = e.getKey().substring(0, e.getKey().length() - suffix.length());
            if (allFiles.contains(p)) {
                continue;
            }
            sb.append("file ").append(e.getKey()).append(" from ").append(e.getValue()).append(" does not hide any other file\n");
        }

        if (sb.length () > 0) {
            fail ("There are some useless hidden files\n" + sb);
        }
    }
    
    /* Too many failures to solve right now.
    public void testLocalizingBundles() throws Exception {
        StringBuilder sb = new StringBuilder();
        for (URL u : NbCollections.iterable(Lookup.getDefault().lookup(ClassLoader.class).getResources("META-INF/MANIFEST.MF"))) {
            String layer;
            InputStream is = u.openStream();
            try {
                layer = new Manifest(is).getMainAttributes().getValue("OpenIDE-Module-Layer");
                if (layer == null) {
                    continue;
                }
            } finally {
                is.close();
            }
            URL base = new URL(u, "../");
            URL layerURL = new URL(base, layer);
            URLConnection connect = layerURL.openConnection();
            connect.setDefaultUseCaches(false);
            for (FileObject fo : NbCollections.iterable(new XMLFileSystem(layerURL).getRoot().getChildren(true))) {
                Object v = getAttributes(fo, base).get(SFS_LB);
                if (v instanceof Exception) {
                    sb.append(layerURL).append(": ").append(v).append("\n");
                }
            }
        }
        if (sb.length() > 0) {
            fail("Some localizing bundle declarations are wrong\n" + sb);
        }
    }
     */

    public void testNoWarningsFromLayerParsing() throws Exception {
        ClassLoader l = Lookup.getDefault().lookup(ClassLoader.class);
        assertNotNull ("In the IDE mode, there always should be a classloader", l);
        
        List<URL> urls = new ArrayList<URL>();
        Enumeration<URL> en = l.getResources("META-INF/MANIFEST.MF");
        while (en.hasMoreElements ()) {
            URL u = en.nextElement();
            InputStream is = u.openStream();
            Manifest mf;
            try {
                mf = new Manifest(is);
            } finally {
                is.close();
            }
            String module = mf.getMainAttributes ().getValue ("OpenIDE-Module");
            if (module == null) {
                continue;
            }
            String layer = mf.getMainAttributes ().getValue ("OpenIDE-Module-Layer");
            if (layer == null) {
                continue;
            }
            URL layerURL = new URL(u, "../" + layer);
            urls.add(layerURL);
        }
        
        File cacheDir;
        File workDir = getWorkDir();
        int i = 0;
        do {
            cacheDir = new File(workDir, "layercache"+i);
            i++;
        } while (!cacheDir.mkdir());
        System.setProperty("netbeans.user", cacheDir.getPath());

        LayerCacheManager bcm = LayerCacheManager.manager(true);
        Logger err = Logger.getLogger("org.netbeans.core.projects.cache");
        TestHandler h = new TestHandler();
        err.addHandler(h);
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        bcm.store(bcm.createEmptyFileSystem(), urls, os);
        assertNoErrors("No errors or warnings during layer parsing", h.errors);
    }

    private static class TestHandler extends Handler {
        List<String> errors = new ArrayList<String>();
        
        TestHandler () {}
        
        public @Override void publish(LogRecord rec) {
            if (Level.WARNING.equals(rec.getLevel()) || Level.SEVERE.equals(rec.getLevel())) {
                errors.add(MessageFormat.format(rec.getMessage(), rec.getParameters()));
            }
        }
        
        List<String> errors() {
            return errors;
        }

        public @Override void flush() {}

        public @Override void close() throws SecurityException {}
    }

    public void testFolderOrdering() throws Exception {
        TestHandler h = new TestHandler();
        Logger.getLogger("org.openide.filesystems.Ordering").addHandler(h);
        Set<List<String>> editorMultiFolders = new HashSet<List<String>>();
        Pattern editorFolder = Pattern.compile("Editors/(application|text)/([^/]+)(/.+|$)");
        Enumeration<? extends FileObject> files = FileUtil.getConfigRoot().getChildren(true);
        while (files.hasMoreElements()) {
            FileObject fo = files.nextElement();
            if (fo.isFolder()) {
                loadChildren(fo);
                assertNull("OpenIDE-Folder-Order attr should not be used on " + fo, fo.getAttribute("OpenIDE-Folder-Order"));
                assertNull("OpenIDE-Folder-SortMode attr should not be used on " + fo, fo.getAttribute("OpenIDE-Folder-SortMode"));
                String path = fo.getPath();
                Matcher m = editorFolder.matcher(path);
                if (m.matches()) {
                    List<String> multiPath = new ArrayList<String>(3);
                    multiPath.add(path);
                    if (m.group(2).endsWith("+xml")) {
                        multiPath.add("Editors/" + m.group(1) + "/xml" + m.group(3));
                    }
                    multiPath.add("Editors" + m.group(3));
                    editorMultiFolders.add(multiPath);
                }
            }
        }
        assertNoErrors("No warnings relating to folder ordering; " +
                "cf: http://deadlock.netbeans.org/job/nbms-and-javadoc/lastSuccessfulBuild/artifact/nbbuild/build/generated/layers.txt", h.errors());
        if (false) {
            // temporarily disable multi-level checking of order, see discussion on dev@ mailing list on how
            // the situation with some MIME types requiring positions and some not should be solved.
            for (List<String> multiPath : editorMultiFolders) {
                List<FileSystem> layers = new ArrayList<FileSystem>(3);
                for (final String path : multiPath) {
                    FileObject folder = FileUtil.getConfigFile(path);
                    if (folder != null) {
                        layers.add(new MultiFileSystem(folder.getFileSystem()) {
                            protected @Override FileObject findResourceOn(FileSystem fs, String res) {
                                FileObject f = fs.findResource(path + '/' + res);
                                return Boolean.TRUE.equals(f.getAttribute("hidden")) ? null : f;
                            }
                        });
                    }
                }
                loadChildren(new MultiFileSystem(layers.toArray(new FileSystem[layers.size()])).getRoot());
                appendFailure("\nNo warnings relating to folder ordering in " + multiPath + 
                        "; cf: http://deadlock.netbeans.org/job/nbms-and-javadoc/lastSuccessfulBuild/artifact/nbbuild/build/generated/layers.txt",
                        h.errors());
                h.errors.clear();
            }
        }
        assertNoFailures();
    }
    private static void loadChildren(FileObject folder) {
        List<FileObject> kids = new ArrayList<FileObject>();
        for (DataObject kid : DataFolder.findFolder(folder).getChildren()) {
            kids.add(kid.getPrimaryFile());
        }
        FileUtil.getOrder(kids, true);
    }

    private static Map<String,Object> getAttributes(FileObject fo, URL base) {
        Map<String,Object> attrs = new TreeMap<String,Object>();
        Enumeration<String> en = fo.getAttributes();
        while (en.hasMoreElements()) {
            String attrName = en.nextElement();
            if (isInstanceAttribute(attrName)) {
                continue;
            }
            Object attr = fo.getAttribute(attrName);
            if (attrName.equals(SFS_LB)) {
                try {
                    String bundleName = (String) attr;
                    URL bundle = new URL(base, bundleName.replace('.', '/') + ".properties");
                    Properties p = new Properties();
                    InputStream is = bundle.openStream();
                    try {
                        p.load(is);
                    } finally {
                        is.close();
                    }
                    String path = fo.getPath();
                    attr = p.get(path);
                    if (attr == null) {
                        attr = new MissingResourceException("No such bundle entry " + path + " in " + bundleName, bundleName, path);
                    }
                } catch (Exception x) {
                    attr = x;
                }
            }
            attrs.put(attrName, attr);
        }
        return attrs;
    }

    private static final String[] SKIPPED = {
        "Templates/GUIForms",
        "Palette/Borders/javax-swing-border-",
        "Palette/Layouts/javax-swing-BoxLayout",
        "Templates/Beans/",
        "PaletteUI/org-netbeans-modules-form-palette-CPComponent",
        "Templates/Ant/CustomTask.java",
        "Templates/Privileged/Main.shadow",
        "Templates/Privileged/JFrame.shadow",
        "Templates/Privileged/Class.shadow",
        "Templates/Classes",
        "Templates/JSP_Servlet",
        "EnvironmentProviders/ProfileTypes/Execution/nb-j2ee-deployment.instance",
        "Shortcuts/D-BACK_QUOTE.shadow",
        "Windows2/Components/", // cannot be loaded with a headless toolkit, so we have to skip these for now
        "Maven/actionTemplate.instance", // template
    };
    private boolean skipFile(FileObject fo) {
        String s = fo.getPath();

        if (s.startsWith ("Templates/") && !s.startsWith ("Templates/Services")) {
            if (s.endsWith (".shadow") || s.endsWith (".java")) {
                return true;
            }
        }

        for (String skipped : SKIPPED) {
            if (s.startsWith(skipped)) {
                return true;
            }
        }
        
        String iof = (String) fo.getAttribute("instanceOf");
        if (iof != null) {
            for (String clz : iof.split("[, ]+")) {
                try {
                    Class<?> c = Lookup.getDefault().lookup(ClassLoader.class).loadClass(clz);
                } catch (ClassNotFoundException x) {
                    // E.g. Services/Hidden/org-netbeans-lib-jsch-antlibrary.instance in ide cluster
                    // cannot be loaded (and would just be ignored) if running without java cluster
                    System.err.println("Warning: skipping " + fo.getPath() + " due to inaccessible interface " + clz);
                    return true;
                }
            }
        }

        return false;
    }

    public void testKeymapOverrides() throws Exception { // #170677
        List<String> warnings = new ArrayList<String>();
        FileObject keymapRoot = FileUtil.getConfigFile("Keymaps");
        if (keymapRoot == null) {
            return;
        }
        FileObject[] keymaps = keymapRoot.getChildren();
        Map<String,Integer> definitionCountById = new HashMap<String,Integer>();
        assertTrue("Too many keymaps for too little bitfield", keymaps.length < 31);
        int keymapFlag = 1;
        for (FileObject keymap : keymaps) {
            for (FileObject shortcut : keymap.getChildren()) {
                DataObject d = DataObject.find(shortcut);
                if (d instanceof DataShadow) {
                    String id = ((DataShadow) d).getOriginal().getPrimaryFile().getPath();
                    Integer prior = definitionCountById.get(id);
                    // a single keymap may provide alternative shortcuts for a given action. Count just once
                    // per keymap.
                    definitionCountById.put(id, prior == null ? keymapFlag : prior | keymapFlag);
                } else if (!d.getPrimaryFile().hasExt("shadow") && !d.getPrimaryFile().hasExt("removed")) {
                    warnings.add("Anomalous file " + d);
                } // else #172453: BrokenDataShadow, OK
            }
            keymapFlag <<= 1;
        }
        int expected = (1 << keymaps.length) - 1;
        for (FileObject shortcut : FileUtil.getConfigFile("Shortcuts").getChildren()) {
            DataObject d = DataObject.find(shortcut);
            if (d instanceof DataShadow) {
                String id = ((DataShadow) d).getOriginal().getPrimaryFile().getPath();
                if (!org.openide.util.Utilities.isMac() && // Would fail on Mac due to applemenu module
                        Integer.valueOf(expected).equals(definitionCountById.get(id)))
                {
                    String layers = Arrays.toString((URL[]) d.getPrimaryFile().getAttribute("layers"));
                    warnings.add(d.getPrimaryFile().getPath() + " " + layers + " useless since " + id + " is bound (somehow) in all keymaps");
                }
            } else if (!d.getPrimaryFile().hasExt("shadow")) {
                warnings.add("Anomalous file " + d);
            }
        }
        // XXX consider also checking for bindings in Shortcuts/ which are overridden in all keymaps or at least NetBeans
        // taking into consideration O- and D- virtual modifiers
        // (this is likely to be more common, e.g. mysterious Shortcuts/D-A.shadow in uml.drawingarea)
        // XXX check for shortcut conflict between Shortcuts and each keymap, e.g. Ctrl-R in Eclipse keymap
        assertNoErrors("Some shortcuts were overridden by keymaps", warnings);
    }
    
    /* XXX too many failures for now, some spurious; use regex, or look for unloc files/folders with loc siblings?
    public void testLocalizedFolderNames() throws Exception {
        List<String> warnings = new ArrayList<String>();
        for (String folder : new String[] {
            "Actions", // many legit failures!
            "OptionsDialog/Actions", // XXX #71280
            "Menu",
            "Toolbars",
            "org-netbeans-modules-java-hints/rules/hints",
            "Editors/FontsColors", // XXX exclude .../Defaults
            "Keymaps",
            "FormDesignerPalette", // XXX match any *Palette?
            "HTMLPalette",
            "XHTMLPalette",
            "JSPPalette",
            "SVGXMLPalette",
            "OptionsExport",
            // "Projects/.../Customizer",
            "QuickSearch",
            "Templates", // XXX exclude Privileged, Recent, Services
        }) {
            FileObject root = FileUtil.getConfigFile(folder);
            if (root == null) {
                continue;
            }
            for (FileObject d : NbCollections.iterable(root.getFolders(true))) {
                if (d.getAttribute("displayName") == null && d.getAttribute("SystemFileSystem.localizingBundle") == null) {
                    warnings.add("No displayName for " + d.getPath());
                }
            }
        }
        assertNoErrors("Some folders need a localized display name", warnings);
    }
    */

    public void testTemplates() throws Exception { // #167205
        List<String> warnings = new ArrayList<String>();
        for (FileObject f : NbCollections.iterable(FileUtil.getConfigFile("Templates").getData(true))) {
            if (!Boolean.TRUE.equals(f.getAttribute("template"))) {
                continue; // will not appear in Template Manager
            }
            if (f.getSize() > 0) {
                continue; // Open in Editor will be enabled
            }
            if (f.getAttribute("instantiatingIterator") != null) { // TemplateWizard.CUSTOM_ITERATOR
                continue; // probably not designed to be edited as text
            }
            if (f.getAttribute("templateWizardIterator") != null) { // TemplateWizard.EA_ITERATOR
                continue; // same
            }
            String path = f.getPath();
            if (path.equals("Templates/Other/file") ||
                path.equals("Templates/Other/group.group") ||
                path.equals("Templates/Classes/Package")) {
                
                // If there're more files like this, consider adding an API
                // to mark them as intentionally non-editable
                continue; // intentionally empty and uneditable
            }
            warnings.add(path + " is empty but has no iterator and will therefore not be editable");
        }
        assertNoErrors("Problems in templates", warnings);
    }

}
