All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.ejb.codegen.StaticRmiStubGenerator Maven / Gradle / Ivy

There is a newer version: 7.2024.1.Alpha1
Show newest version
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */
// Portions Copyright 2019-2022 Payara Foundation and/or its affiliates
// Payara Foundation and/or its affiliates elects to include this software in this distribution under the GPL Version 2 license.

package com.sun.ejb.codegen;

import com.sun.enterprise.config.serverbeans.JavaConfig;
import com.sun.enterprise.deployment.Application;
import com.sun.enterprise.deployment.EjbBundleDescriptor;
import com.sun.enterprise.deployment.EjbDescriptor;
import com.sun.enterprise.deployment.util.TypeUtil;
import com.sun.enterprise.util.OS;
import com.sun.enterprise.util.i18n.StringManager;
import com.sun.logging.LogDomains;
import org.glassfish.api.admin.ServerEnvironment;
import org.glassfish.api.deployment.DeploymentContext;
import org.glassfish.deployment.common.ClientArtifactsManager;
import org.glassfish.ejb.spi.CMPDeployer;
import org.glassfish.hk2.api.ServiceLocator;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * This class is used to generate the RMI-IIOP version of a 
 * remote business interface.
 */

public class StaticRmiStubGenerator {

    private static final StringManager localStrings = StringManager.getManager(StaticRmiStubGenerator.class);

     private static final Logger _logger =
                LogDomains.getLogger(StaticRmiStubGenerator.class, LogDomains.EJB_LOGGER);

     private static final String ORG_OMG_STUB_PREFIX  = "org.omg.stub.";

     private List rmicOptionsList;

    /**
     * This class is only instantiated internally.
     */
    public StaticRmiStubGenerator(ServiceLocator services) {
        // Find java path

        // Try this jre's parent
        String jreHome = System.getProperty("java.home");
        File jdkDir = null;
        if(jreHome != null) {
            // on the mac the java.home does not point to the jre
            // subdirectory.
            if (OS.isDarwin()) {
                jdkDir = new File(jreHome);
            } else {
                jdkDir = (new File(jreHome)).getParentFile();       //jdk_dir/jre/..
            }

            jdkDir = getValidDirectory(jdkDir);
        }

        if(jdkDir == null) {
            // Check for "JAVA_HOME" -- which is set via Server.xml during initialization
            // of the Server that is calling us.

            String jh = System.getProperty("JAVA_HOME");
            if(jh != null) {
                jdkDir = getValidDirectory(new File(jh));  // e.g. c:/ias7/jdk
            }
        }

/** XXX ???
        if(jdkDir == null) {
            //Somehow, JAVA_HOME is not set. Try the "well-known" location...
            if(installRoot != null) {
                jdkDir = getValidDirectory(new File(installRoot + "/jdk"));

            }
        }
** XXX **/

        if(jdkDir == null) {
            _logger.warning("Cannot identify JDK location.");
        }

        JavaConfig jc = services.getService(JavaConfig.class,
                ServerEnvironment.DEFAULT_INSTANCE_NAME);
        String rmicOptions = jc.getRmicOptions();

        rmicOptionsList = new ArrayList();
        StringTokenizer st = new StringTokenizer(rmicOptions, " ");
        while (st.hasMoreTokens()) {
            String op = (String) st.nextToken();
            rmicOptionsList.add(op);
            _logger.log(Level.INFO, "Detected Rmic option: " + op);
        }
    }

    /**
     * Generates and compiles the necessary impl classes, stubs and skels.
     *
     * 
     *
     * This method makes the following assumptions:
     *    - the deployment descriptor xmls are registered with Config
     *    - the class paths are registered with Config
     *
     * @@@
     * In case of re-deployment, the following steps should happen before:
     *    - rename the src dir from previous deployment (ex. /app/pet-old)
     *    - rename the stubs dir from previous deployment (ex. /stub/pet-old)
     *    - explode the ear file (ex. /app/petstore)
     *    - register the deployment descriptor xml with config
     *    - register the class path with config
     *
     * After successful completion of this method, the old src and sutbs
     * directories may be deleted.
     *
     * 
* * @param deploymentCtx * * @return array of the client stubs files as zip items or empty array * */ public void ejbc(DeploymentContext deploymentCtx) throws Exception { // stubs dir for the current deployment File stubsDir = deploymentCtx.getScratchDir("ejb"); String explodedDir = deploymentCtx.getSource().getURI().getSchemeSpecificPart(); // deployment descriptor object representation EjbBundleDescriptor ejbBundle = deploymentCtx.getModuleMetaData(EjbBundleDescriptor.class); long startTime = now(); // class path to be used for this application during javac & rmic String classPath = deploymentCtx.getTransientAppMetaData(CMPDeployer.MODULE_CLASSPATH, String.class); // Warning: A class loader is passed in while constructing the // application object final ClassLoader jcl = ejbBundle.getClassLoader(); // stubs dir is used as repository for code generator final String gnrtrTMP = stubsDir.getCanonicalPath(); // ---- EJB DEPLOYMENT DESCRIPTORS ------------------------------- // The main use-case we want to support is the one where existing // stand-alone java clients that access ejbs hosted in our appserver // directly through CosNaming need the generated stubs. We don't want to // force them to run rmic themselves so it's better for them // just to tell us during the deployment of an ejb client app // or ejb app that we should run rmic and put the stubs in the // client.jar. Turning on the deployment-time rmic flag ONLY // controls the generation of rmic stubs. Dynamic stubs will be used // in the server, in the Application Client container, and in // stand-alone clients that instantiate our naming provider. progress(localStrings.getStringWithDefault ("generator.processing_beans", "Processing beans...")); // ---- END OF EJB DEPLOYMENT DESCRIPTORS -------------------------- // ---- RMIC ALL STUB CLASSES -------------------------------------- Set allStubClasses = new HashSet(); // stubs classes for ejbs within this app that need rmic Set ejbStubClasses = getStubClasses(jcl, ejbBundle); allStubClasses.addAll(ejbStubClasses); // Compile and RMIC all Stubs rmic(classPath, allStubClasses, stubsDir, gnrtrTMP, explodedDir); _logger.log(Level.INFO, "[RMIC] RMIC execution time: " + (now() - startTime) + " msec"); // ---- END OF RMIC ALL STUB CLASSES ------------------------------- // Create list of all server files and client files List allClientFiles = new ArrayList(); // assemble the client files addGeneratedFiles(allStubClasses, allClientFiles, stubsDir); ClientArtifactsManager cArtifactsManager = ClientArtifactsManager.get(deploymentCtx); for (String file : allClientFiles) { cArtifactsManager.add(stubsDir, new File(file)); } _logger.log(Level.INFO, "ejbc.end", deploymentCtx.getModuleMetaData(Application.class).getRegistrationName()); _logger.log(Level.INFO, "[RMIC] Total time: " + (now() - startTime) + " msec"); } /** * Compile all the generated .java files, run rmic on them. * * @param classPath class path for javac & rmic * @param stubClasses additional classes to be compilled with * the other files * @param destDir destination directory for javac & rmic * @param repository repository for code generator * @param explodedDir exploded directory for .class files * * @exception GeneratorException if an error during code generation * @exception IOException if an i/o error */ private void rmic(String classPath, Set stubClasses, File destDir, String repository, String explodedDir) throws GeneratorException, IOException { if( stubClasses.size() == 0 ) { _logger.log(Level.INFO, "[RMIC] No code generation required"); return; } progress(localStrings.getStringWithDefault( "generator.compiling_rmi_iiop", "Compiling RMI-IIOP code.")); List cmds = new ArrayList(); cmds.addAll(rmicOptionsList); cmds.add("-classpath"); StringBuilder sb = new StringBuilder().append(System.getProperty("java.class.path")); sb.append(File.pathSeparator).append(explodedDir) .append(File.pathSeparator).append(repository) .append(File.pathSeparator).append(classPath); cmds.add(sb.toString()); cmds.add("-d"); cmds.add(destDir.toString()); cmds.addAll(stubClasses); _logger.info("[RMIC] options: " + cmds); ByteArrayOutputStream baos = new ByteArrayOutputStream(); org.glassfish.rmic.Main compiler = new org.glassfish.rmic.Main(baos, "rmic"); boolean success = compiler.compile(cmds.toArray(new String[cmds.size()])); //success = true; // it ALWAYS returns an "error" if -Xnocompile is used!! String output = baos.toString(); if (!success) { _logger.warning("[RMIC] Errors: " + output); throw new GeneratorException( localStrings.getString("generator.rmic_compilation_failed_see_log")); } } /** * Assembles the name of the client jar files into the given vector. * * @param stubClasses classes that required rmic * @param allClientFiles List that contains all client jar files * @param stubsDir current stubsnskells dir for the app */ private void addGeneratedFiles(Set stubClasses, List allClientFiles, File stubsDir) { for (String stubClass : stubClasses) { String stubFile = stubsDir.toString() + File.separator + getStubName(stubClass).replace('.', File.separatorChar) + ".class"; allClientFiles.add(stubFile); } _logger.log(Level.INFO, "[RMIC] Generated client files: " + allClientFiles); } private String getStubName(String fullName) { String className = fullName; String packageName = ""; int lastDot = fullName.lastIndexOf('.'); if (lastDot != -1) { className = fullName.substring(lastDot+1, fullName.length()); packageName = fullName.substring(0, lastDot+1); } String stubName = packageName + "_" + className + "_Stub"; if(isSpecialPackage(fullName)) stubName = ORG_OMG_STUB_PREFIX + stubName; return stubName; } private boolean isSpecialPackage(String name) { // these package names are magic. RMIC puts any home/remote stubs // into a different directory in these cases. // 4845896 bnevins, April 2003 // this is really an error. But we have enough errors. Let's be forgiving // and not allow a NPE out of here... if(name == null) return false; // Licensee bug 4959550 // if(name.startsWith("com.sun.") || name.startsWith("javax.")) if(name.startsWith("javax.") || name.startsWith("jakarta.")) { return true; } return false; } private Set getRemoteSuperInterfaces(ClassLoader jcl, String homeRemoteIntf) throws ClassNotFoundException { // all super interfaces of home or remote that need to be // processed for stubs. Set allSuperInterfaces = TypeUtil.getSuperInterfaces(jcl, homeRemoteIntf,"java.rmi.Remote"); Set remoteSuperInterfaces = new HashSet(); Iterator iter = allSuperInterfaces.iterator(); while (iter.hasNext()) { String intfName = (String) iter.next(); Class intfClass = jcl.loadClass(intfName); if ( java.rmi.Remote.class.isAssignableFrom(intfClass) && !(intfName.equals("jakarta.ejb.EJBHome")) && !(intfName.equals("jakarta.ejb.EJBObject")) ) { remoteSuperInterfaces.add(intfName); } } return remoteSuperInterfaces; } private Set getStubClasses(ClassLoader jcl, EjbBundleDescriptor ejbBundle) throws IOException, ClassNotFoundException { Set stubClasses = new HashSet(); for (Iterator iter = ejbBundle.getEjbs().iterator(); iter.hasNext();) { EjbDescriptor desc = (EjbDescriptor) iter.next(); if( desc.isRemoteInterfacesSupported() ) { String home = desc.getHomeClassName(); String remote = desc.getRemoteClassName(); stubClasses.add(home); Set homeSuperIntfs = getRemoteSuperInterfaces(jcl, home); stubClasses.addAll(homeSuperIntfs); stubClasses.add(remote); Set remoteSuperIntfs = getRemoteSuperInterfaces(jcl, remote); stubClasses.addAll(remoteSuperIntfs); } } return stubClasses; } private long now() { return System.currentTimeMillis(); } private void progress(String message) { try { _logger.log(Level.INFO, message); } catch(Throwable t) { _logger.log(Level.FINER,"Cannot set status message",t); } } private File getValidDirectory(File f) { try { if(f != null && f.isDirectory()) { return f.getCanonicalFile(); } } catch (IOException e) { _logger.log(Level.INFO, e.getMessage(), e); } return null; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy