/*
 * 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.apache.openjpa.lib.meta;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLDecoder;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.NoSuchElementException;

import org.apache.openjpa.lib.util.ClassUtil;
import org.apache.openjpa.lib.util.J2DoPrivHelper;
import org.apache.openjpa.lib.util.MultiClassLoader;

/**
 * Iterator over all metadata resources that might contain the
 * metadata for a given class, starting with the most general. Assumes that
 * package-level resources are named "package.&lt;suffix&gt;".
 *
 * @author Abe White
 */
public class ClassMetaDataIterator implements MetaDataIterator {

    private final ClassLoader _loader;
    private final List<String> _locs;
    private int _loc = -1;
    private final List<URL> _urls = new ArrayList<>(3);
    private int _url = -1;

    /**
     * Constructor; supply the class whose metadata to find, the suffix
     * of metadata files, and whether to parse top-down or bottom-up.
     */
    public ClassMetaDataIterator(Class<?> cls, String suffix, boolean topDown) {
        this(cls, suffix, null, topDown);
    }

    /**
     * Constructor; supply the class whose metadata to find, the suffix
     * of metadata files, and whether to parse top-down or bottom-up.
     */
    public ClassMetaDataIterator(Class<?> cls, String suffix,
            ClassLoader loader, boolean topDown) {
        // skip classes that can't have metadata
        if (cls != null && (cls.isPrimitive()
            || cls.getName().startsWith("java.")
            || cls.getName().startsWith("javax.")
            || cls.getName().startsWith("jakarta."))) {
            _loader = null;
            _locs = Collections.emptyList();
            return;
        }

        if (loader == null) {
            MultiClassLoader multi = AccessController
                .doPrivileged(J2DoPrivHelper.newMultiClassLoaderAction());
            multi.addClassLoader(MultiClassLoader.SYSTEM_LOADER);
            multi.addClassLoader(MultiClassLoader.THREAD_LOADER);
            multi.addClassLoader(getClass().getClassLoader());
            if (cls != null)
            {
                ClassLoader clsLoader = (ClassLoader)
                    AccessController.doPrivileged(
                        J2DoPrivHelper.getClassLoaderAction(cls));
                if (clsLoader != null)
                    multi.addClassLoader(clsLoader);
            }
            loader = multi;
        }
        _loader = loader;

        // collect the set of all possible metadata locations; start with
        // system locations
        _locs = new ArrayList<>();
        _locs.add("META-INF/package" + suffix);
        _locs.add("WEB-INF/package" + suffix);
        _locs.add("package" + suffix);

        // put this legacy location at the end regardless of whether we're
        // going top down or bottom up so we don't have to parse it as often
        // during testing
        if (!topDown)
            _locs.add("system" + suffix);

        if (cls != null) {
            // also check:
            // 1. for each package from the top down to cls' package:
            // <path>/package<suffix>
            // <path>/<package-name><suffix> (legacy support)
            // <path>/../<package-name><suffix> (legacy support)
            // 2. <path>/<class-name><suffix>
            String pkg = ClassUtil.getPackageName(cls).replace('.', '/');
            if (pkg.length() > 0) {
                int idx, start = 0;
                String pkgName, path, upPath = "";
                do {
                    idx = pkg.indexOf('/', start);
                    if (idx == -1) {
                        pkgName = (start == 0) ? pkg : pkg.substring(start);
                        path = pkg + "/";
                    } else {
                        pkgName = pkg.substring(start, idx);
                        path = pkg.substring(0, idx + 1);
                    }

                    _locs.add(path + "package" + suffix);
                    _locs.add(path + pkgName + suffix); // legacy
                    _locs.add(upPath + pkgName + suffix); // legacy
                    if (idx == -1)
                        _locs.add(path + ClassUtil.getClassName(cls) + suffix);

                    start = idx + 1;
                    upPath = path;
                }
                while (idx != -1);
            } else {
                // <class-name><suffix> for top-level classes
                _locs.add(cls.getName() + suffix);
            }
        }
        if (topDown)
            _locs.add("system" + suffix); // legacy
        else
            Collections.reverse(_locs);
    }

    @Override
    public boolean hasNext() throws IOException {
        Enumeration<URL> e;
        while (_url + 1 >= _urls.size()) {
            if (++_loc >= _locs.size())
                return false;

            _url = -1;
            _urls.clear();
            try {
                e = AccessController.doPrivileged(
                    J2DoPrivHelper.getResourcesAction(
                        _loader, _locs.get(_loc)));
            } catch (PrivilegedActionException pae) {
                throw (IOException) pae.getException();
            }
            while (e.hasMoreElements())
                _urls.add(e.nextElement());
        }
        return true;
    }

    @Override
    public URL next() throws IOException {
        if (!hasNext())
            throw new NoSuchElementException();
        return _urls.get(++_url);
    }

    @Override
    public InputStream getInputStream() throws IOException {
        if (_url == -1 || _url >= _urls.size())
            throw new IllegalStateException();
        try {
            return AccessController.doPrivileged(
                J2DoPrivHelper.openStreamAction(_urls.get(_url)));
        } catch (PrivilegedActionException pae) {
            throw (IOException) pae.getException();
        }
    }

    @Override
    public File getFile() throws IOException {
        if (_url == -1 || _url >= _urls.size())
            throw new IllegalStateException();
        File file = new File(URLDecoder.decode((_urls.get(_url)).getFile()));
        return ((AccessController.doPrivileged(
            J2DoPrivHelper.existsAction(file))).booleanValue()) ? file:null;
    }

    @Override
    public void close() {
    }
}