/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.internal.jpa.deployment;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.eclipse.persistence.jpa.Archive;

/**
 * This is an implementation of {@link Archive} when container returns a file:
 * url that refers to a directory that contains an exploded jar file.
 * e.g. file:/tmp/a_ear/ejb_jar
 *
 * @author Sanjeeb.Sahoo@Sun.COM
 */
public class DirectoryArchive extends ArchiveBase implements Archive {
    /*
     * Implementation Note: This class does not have any dependency on either
     * EclipseLink or GlassFish implementation classes. Please retain this separation.
     */

    /**
     * The directory this archive represents.
     */
    private File directory;

    /**
     * The file entries that this archive contains.
     */
    private List<String> entries = new ArrayList<String>();

    @SuppressWarnings("unused")
    private Logger logger;

    @SuppressWarnings("deprecation")
    public DirectoryArchive(File directory, String descriptorLocation) throws MalformedURLException {
        this(directory, descriptorLocation, Logger.global);
    }

    public DirectoryArchive(File directory, String descriptorLocation, Logger logger)
            throws MalformedURLException {
        super();
        logger.entering("DirectoryArchive", "DirectoryArchive",
                        new Object[]{directory});
        this.logger = logger;
        if (!directory.isDirectory()) {
            // should never reach here, hence the msg is not internationalized.
            throw new IllegalArgumentException(directory +
                    " is not a directory. " + // NOI18N
                    "If it is a jar file, then use JarFileArchive."); // NOI18N
        }
        this.directory = directory;
        rootURL = directory.toURI().toURL();
        this.descriptorLocation = descriptorLocation;
        logger.logp(Level.FINER, "DirectoryArchive", "DirectoryArchive",
                "rootURL = {0}", rootURL);
        init(this.directory, this.directory); // initialize entries
    }

    private void init(File top, File directory) {
        File[] dirFiles = directory.listFiles();
        if (dirFiles != null) {
            for (File file : dirFiles) {
                if (file.isDirectory()) {
                    continue; // exclude dir entries
                }

                // add only the relative path from the top.
                // note: we use unix style path
                String entryName = file.getPath().replace(File.separator, "/") // NOI18N
                    .substring(top.getPath().length() + 1);
                entries.add(entryName);
            }
            File[] subDirs = directory.listFiles(new FileFilter() {
                @Override
                public boolean accept(File pathname) {
                    return pathname.isDirectory();
                }
            });
            if (subDirs != null) {
                for (File subDir : subDirs) {
                    init(top, subDir); // recursion
                }
            }
        }
    }

    @Override
    public Iterator<String> getEntries() {
        return entries.iterator();
    }

    @Override
    public InputStream getEntry(String entryPath) throws IOException {
        File f = getFile(entryPath);
        InputStream is = f.exists() ? new FileInputStream(f) : null;
        return is;
    }

    @Override
    public URL getEntryAsURL(String entryPath) throws IOException {
        File f = getFile(entryPath);
        URL url = f.exists() ? f.toURI().toURL() : null;
        return url;
    }

    private File getFile(String entryPath) {
        File f = new File(directory, entryPath);
        return f;
    }

    @Override
    public void close() {
        // nothing to close. it's caller's responsibility to close
        // any InputStream returned by getEntry().
    }

}

