/*
 * 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.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.lang.instrument.IllegalClassFormatException;
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
     * @throws MalformedURLException
     */
    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
     * @throws MalformedURLException
     */
    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
     * @param persistenceXMLLocation
     */
    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 (IllegalClassFormatException 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;
                    } catch (ClassNotFoundException e) {
                        AbstractSessionLog.getLog().logThrowable(AbstractSessionLog.WARNING, AbstractSessionLog.WEAVER, e);
                        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[]{};
    }
}
