/*
 * Copyright (c) 1998, 2020 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.DefaultSessionLog;
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){
            ((DefaultSessionLog)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 entries = sourceArchive.getEntries();
                while (entries.hasNext()){
                    String entryName = (String)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[]{};
    }
}
