/*
 * Copyright (c) 1998, 2022 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.tools.weaving.jpa;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Iterator;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;

import org.eclipse.persistence.exceptions.StaticWeaveException;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.jpa.deployment.ArchiveFactoryImpl;
import org.eclipse.persistence.internal.jpa.deployment.PersistenceUnitProcessor;
import org.eclipse.persistence.internal.jpa.weaving.AbstractStaticWeaveOutputHandler;
import org.eclipse.persistence.internal.jpa.weaving.StaticWeaveDirectoryOutputHandler;
import org.eclipse.persistence.internal.jpa.weaving.StaticWeaveJAROutputHandler;
import org.eclipse.persistence.internal.localization.ToStringLocalization;
import org.eclipse.persistence.jpa.Archive;
import org.eclipse.persistence.logging.AbstractSessionLog;
import org.eclipse.persistence.logging.SessionLog;

/**
 * <p>
 * <b>Description</b>: The StaticWeaveProcessor controls the static weaving process.  It is invoked by both the command line
 * StaticWeave class and the StaticWeaveAntTask.
 * <p>
 * <b>Responsibilities</b>: Process the source classes, performs weaving as necessary out outputs to the target
 */
@SuppressWarnings("deprecation")
public class StaticWeaveProcessor {
    private URL source;
    private URL target;
    private URL persistenceInfo;
    private String persistenceXMLLocation;
    private Writer logWriter;
    private ClassLoader classLoader;
    private int logLevel = SessionLog.OFF;

    private static final int NUMBER_OF_BYTES = 1024;

    /**
     * Constructs an instance of StaticWeaveProcessor
     * @param source the name of the location to be weaved
     * @param target the name of the location to be weaved to
     */
    public StaticWeaveProcessor(String source, String target)throws MalformedURLException{
        if (source != null) {
            this.source=new File(source).toURL();
        }
        if (target != null) {
            this.target=new File(target).toURL();
        }
    }

    /**
     * Constructs an instance of StaticWeaveProcessor
     * @param source the File object of the source to be weaved
     * @param target the File object of the target to be weaved to
     */
    public StaticWeaveProcessor(File source, File target)throws MalformedURLException {
        this.source=source.toURL();
        this.target=target.toURL();
    }

    /**
     * Constructs an instance of StaticWeaveProcessor
     * @param source the URL of the source to be weaved
     * @param target the URL of the target to be weaved to
     */
    public StaticWeaveProcessor(URL source, URL target){
        this.source = source;
        this.target = target;
    }

    /**
     * The method allows user to specify the output for the log message.
     * @param logWriter the location where the log message writes to. the default value is standard out
     */
    public void setLog(Writer logWriter){
        this.logWriter = logWriter;
    }

    /**
     * The method allows user to define nine levels EclipseLink logging.
     * @param level - the integer value of log level. default is OFF.
     */
    public void setLogLevel(int level){
        this.logLevel = level;
    }

    /**
     * Set the user classloader.
     */
    public void setClassLoader(ClassLoader classLoader){
        this.classLoader=classLoader;
    }

    /**
     * Set an explicitly identified URL of the location containing persistence.xml.
     * @param persistenceInfo the URL of the location containing persistence.xml, the URL
     * must point to the root of META-INF/persistence.xml
     */
    public void setPersistenceInfo(URL persistenceInfo){
        this.persistenceInfo = persistenceInfo;
    }

    /**
     * Set an explicitly identified the location containing persistence.xml.
     * @param persistenceInfoPath the path of the location containing persistence.xml, the path
     * must point to the root of META-INF/persistence.xml
     */
    public void setPersistenceInfo(String persistenceInfoPath) throws MalformedURLException{
        if (persistenceInfoPath != null){
            this.persistenceInfo = new File(persistenceInfoPath).toURL();
        }
    }

    public String getPersistenceXMLLocation() {
        return persistenceXMLLocation;
    }

    /**
     * Set a specific location to look for persistence.xml
     * by default we will look in META-INF/persistence.xml
     */
    public void setPersistenceXMLLocation(String persistenceXMLLocation) {
        this.persistenceXMLLocation = persistenceXMLLocation;
    }

    /**
     * Set an explicitly identified the location containing persistence.xml.
     * @param persistenceInfoFile the file containing persistence.xml, the file
     * should contain META-INF/persistence.xml
     */
    public void setPersistenceInfo(File persistenceInfoFile) throws MalformedURLException{
        if (persistenceInfoFile!=null){
            this.persistenceInfo=persistenceInfoFile.toURL();
        }
    }


    /**
     * This method performs weaving function on the class individually from the specified source.
     */
    public void performWeaving() throws URISyntaxException,MalformedURLException,IOException{
        preProcess();
        process();
    }

    /**
     * INTERNAL:
     * This method perform all necessary steps(verification, pre-build the target directory)
     * prior to the invocation of the weaving function.
     */
    private void preProcess() throws URISyntaxException,MalformedURLException{
        //Instantiate default session log
        AbstractSessionLog.getLog().setLevel(this.logLevel);
        if(logWriter!=null){
            AbstractSessionLog.getLog().setWriter(logWriter);
        }

        //Make sure the source is existing
        if(!(new File(Helper.toURI(source)).exists())){
            throw StaticWeaveException.missingSource();
        }

        URI targetURI = Helper.toURI(target);
        //Verification target and source, two use cases create warning or exception.
        //1. If source is directory and target is jar -
        //   This will lead unknown outcome, user attempt to use this tool to pack outcome into a Jar.
        //   Warning message will be logged, this is can be worked around by other utilities.
        //2. Both source and target are specified as a same jar -
        //   User was trying to perform weaving in same Jar which is not supported, an Exception will be thrown.
        if(isDirectory(source) && targetURI.toString().endsWith(".jar")){
            AbstractSessionLog.getLog().log(SessionLog.WARNING, SessionLog.WEAVER, ToStringLocalization.buildMessage("staticweave_processor_unknown_outcome", new Object[]{null}), null, false);
        }

        if(!isDirectory(source) && target.toString().equals(source.toString())){
            throw StaticWeaveException.weaveInplaceForJar(source.toString());
        }

        //pre-create target if it is directory and dose not exist.
        //Using the method File.isDirectory() is not enough to determine what the type(dir or jar)
        //of the target(specified by URL)that user want to create. File.isDirectory() will return false in
        //two possibilities, the location either is not directory or the location dose not exist.
        //Therefore pre-build of the directory target is required. Pre-build for the file(JAR) target
        //is not required since it gets built automatically by opening outputstream.
        File targetDir = new File(targetURI);
        if(!targetDir.exists()){
            if(!targetURI.toString().endsWith(".jar")){
                if (!targetDir.mkdirs()) {
                    AbstractSessionLog.getLog().log(AbstractSessionLog.FINE, AbstractSessionLog.WEAVER,
                            ToStringLocalization.buildMessage("staticweave_processor_dir_not_created", new Object[]{targetDir}));
                }
                //if directory fails to build, which may leads to unknown outcome since it will
                //be treated as single file in the class StaticWeaveHandler and automatically gets built
                //by outputstream.

                //re-assign URL.
                target = targetDir.toURL();
            }
        }
    }

    /**
     * INTERNAL:
     * The method performs weaving function
     */
    private void process() throws IOException,URISyntaxException{
        // Instantiate output handler.
        AbstractStaticWeaveOutputHandler swoh;
        if (isDirectory(this.target)) {
            swoh= new StaticWeaveDirectoryOutputHandler(this.source,this.target);
        }else{
            swoh= new StaticWeaveJAROutputHandler(new JarOutputStream(new FileOutputStream(new File(Helper.toURI(this.target)))));
        }

        // Instantiate classloader.
        this.classLoader = (this.classLoader == null)? Thread.currentThread().getContextClassLoader():this.classLoader;
        this.classLoader = new URLClassLoader(getURLs(), this.classLoader);

        // Instantiate the classtransformer, we check if the persistenceinfo URL has been specified.
        StaticWeaveClassTransformer classTransformer=null;
        if (persistenceInfo!=null) {
            classTransformer = new StaticWeaveClassTransformer(persistenceInfo, persistenceXMLLocation, this.classLoader,this.logWriter,this.logLevel);
        } else{
            classTransformer = new StaticWeaveClassTransformer(source, persistenceXMLLocation, this.classLoader,this.logWriter,this.logLevel);
        }

        // Starting process.
        Archive sourceArchive =(new ArchiveFactoryImpl()).createArchive(source, null, null);
        if (sourceArchive != null) {
            try {
                Iterator<String> entries = sourceArchive.getEntries();
                while (entries.hasNext()){
                    String entryName = entries.next();
                    InputStream entryInputStream = sourceArchive.getEntry(entryName);

                    // Add a directory entry
                    swoh.addDirEntry(getDirectoryFromEntryName(entryName));

                    // Add a regular entry
                    JarEntry newEntry = new JarEntry(entryName);

                    // Ignore non-class files.
                    if (!entryName.endsWith(".class") || "module-info.class".equals(entryName)) {
                        swoh.addEntry(entryInputStream, newEntry);
                        continue;
                    }

                    String className = PersistenceUnitProcessor.buildClassNameFromEntryString(entryName) ;

                    byte[] originalClassBytes=null;
                    byte[] transferredClassBytes=null;
                    try {
                        Class<?> thisClass = this.classLoader.loadClass(className);
                        // If the class is not in the classpath, we simply copy the entry
                        // to the target(no weaving).
                        if (thisClass == null){
                            swoh.addEntry(entryInputStream, newEntry);
                            continue;
                        }

                        // Try to read the loaded class bytes, the class bytes is required for
                        // classtransformer to perform transfer. Simply copy entry to the target(no weaving)
                        // if the class bytes can't be read.
                        InputStream is = this.classLoader.getResourceAsStream(entryName);
                        if (is!=null){
                            ByteArrayOutputStream baos = null;
                            try{
                                baos = new ByteArrayOutputStream();
                                byte[] bytes = new byte[NUMBER_OF_BYTES];
                                int bytesRead = is.read(bytes, 0, NUMBER_OF_BYTES);
                                while (bytesRead >= 0){
                                    baos.write(bytes, 0, bytesRead);
                                    bytesRead = is.read(bytes, 0, NUMBER_OF_BYTES);
                                }
                                originalClassBytes = baos.toByteArray();
                            } finally {
                                baos.close();
                                is.close();
                            }
                        } else {
                            swoh.addEntry(entryInputStream, newEntry);
                            continue;
                        }

                        // If everything is OK so far, we perform the weaving. we need three parameters in order to
                        // class to perform weaving for that class, the class name,the class object and class bytes.
                        transferredClassBytes = classTransformer.transform(className.replace('.', '/'), thisClass, originalClassBytes);

                        // If transferredClassBytes is null means the class dose not get woven.
                        if (transferredClassBytes!=null){
                            swoh.addEntry(newEntry, transferredClassBytes);
                        } else {
                            swoh.addEntry(entryInputStream, newEntry);
                        }
                    } catch (Throwable e) {
                        AbstractSessionLog.getLog().logThrowable(AbstractSessionLog.WARNING, AbstractSessionLog.WEAVER, e);
                        // Anything went wrong, we need log a warning message, copy the entry to the target and
                        // process next entry.
                        swoh.addEntry(entryInputStream, newEntry);
                        continue;
                    } finally {
                        // Need close the inputstream for current entry before processing next one.
                        entryInputStream.close();
                    }
                }
            } finally {
                sourceArchive.close();
                swoh.closeOutputStream();
            }
        }
    }

    //Extract directory from entry name.
    public static String getDirectoryFromEntryName(String entryName){
        String result="";
        if (entryName==null ) {
            return result;
        }
        if(entryName.lastIndexOf('/')>=0){
            result=entryName.substring(0, entryName.lastIndexOf('/'))+File.separator;
        }
        return result;
    }

    /**
     * Determine whether or not the URL is pointing to directory.
     */
    private boolean isDirectory(URL url) throws URISyntaxException{
        File file = new File(Helper.toURI(url));
        if (file.isDirectory()) {
            return true;
        }else{
            return false;
        }
    }

    /**
     * Generate URL array for specified source and persistenceinfo.
     */
    private URL[] getURLs(){
        if((this.source!=null) && (this.persistenceInfo!=null)){
            return new URL[]{this.persistenceInfo,this.source};
        } else if(this.source!=null){
            return new URL[]{this.source};
        } else if (this.persistenceInfo!=null){
            return new URL[]{this.persistenceInfo};
        }
        return new URL[]{};
    }
}
