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

org.glassfish.appclient.client.acc.AppClientInfo 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.
 */

package org.glassfish.appclient.client.acc;

import com.sun.enterprise.deployment.Application;
import com.sun.enterprise.deployment.ApplicationClientDescriptor;
import com.sun.enterprise.deployment.PersistenceUnitDescriptor;
import com.sun.enterprise.deployment.archivist.Archivist;
import com.sun.enterprise.deployment.util.AnnotationDetector;
import com.sun.enterprise.util.LocalStringManager;
import com.sun.enterprise.util.LocalStringManagerImpl;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import jakarta.inject.Inject;
import jakarta.inject.Provider;

import org.glassfish.apf.AnnotationProcessorException;
import org.glassfish.api.deployment.InstrumentableClassLoader;
import org.glassfish.api.deployment.archive.ReadableArchive;
import org.glassfish.appclient.common.Util;
import org.glassfish.hk2.api.ServiceLocator;
import org.jvnet.hk2.annotations.Service;
import org.xml.sax.SAXParseException;

import jakarta.persistence.EntityManagerFactory;

/**
 *Represents information about the app client, regardless of what type of
 *archive (jar or directory) it is stored in or what type of module 
 *(app client or nested within an ear) that archive holds.
 *
 *@author tjquinn
 */
@Service
public abstract class AppClientInfo {

    public static final String USER_CODE_IS_SIGNED_PROPERTYNAME = "com.sun.aas.user.code.signed";
    
    private static final String SIGNED_USER_CODE_PERMISSION_TEMPLATE_NAME = "jwsclientSigned.policy";
    
    private static final String UNSIGNED_USER_CODE_PERMISSION_TEMPLATE_NAME = "jwsclientUnsigned.policy";
    
    private static final String CODE_BASE_PLACEHOLDER_NAME = "com.sun.aas.jws.client.codeBase";
    
    /** logger */
    protected Logger _logger;
    
//    /** abstract representation of the storage location */
//    private ReadableArchive appClientArchive = null;

//    /** original appclient (file or directory) */
//    private File appClientArchive = null;
//    private ReadableArchive appClient;

    /** abstract archivist able to operate on the module in the location 
      * (specified by archive */
    private Archivist archivist = null;
    
    /** main class name as the user specified it on the command line */
    protected String mainClassFromCommandLine;
    
    /**
     *main class to be used - could come from the command line or from the 
     *manifest of the selected app client archive 
     */
    protected String mainClassNameToRun = null;

    /** class loader - cached */
    private ClassLoader classLoader = null;
    
    /** indicates if the app client has been launched using Java Web Start */
    protected boolean isJWS = false;

    /**
     * descriptor from the app client module or a default one for the
     * .class file case and the regular java launch with main class case
     */
    private ApplicationClientDescriptor acDesc = null;
    
    /** access to the localizable strings */
    private static final LocalStringManager localStrings =
            new LocalStringManagerImpl(AppClientInfo.class);

// XXX Mitesh helping to update this
//    private PersistenceUnitLoader.ApplicationInfo puAppInfo;

//    /**
//     *Creates a new instance of AppClientInfo.  Always invoked from subclasse
//     *because AppClientInfo is abstract.
//     *

// *Note that any code instantiationg one of the concrete subclasses MUST // *invoke completeInit after this super.constructor has returned. // * // *@param isJWS indicates if ACC has been launched using Java Web Start // *@param logger the logger to use for messages // *@param archive the AbstractArchive for the app client module or // * directory being launched // *@param archivist the Archivist corresponding to the type of module // * in the archive // *@param mainClassFromCommandLine the main class name specified on the // * command line (null if not specified) // */ // public AppClientInfo(boolean isJWS, Logger logger, ReadableArchive appClientarchive, // Archivist archivist, String mainClassFromCommandLine) { // this.isJWS = isJWS; // _logger = logger; // this.appClientArchive = appClientarchive; // this.archivist = archivist; // this.mainClassFromCommandLine = mainClassFromCommandLine; // } /** * Creates a new AppClientInfo for a main class file. * * @param isJWS * @param logger * @param mainClassFromCommandLine */ public AppClientInfo(boolean isJWS, Logger logger, String mainClassFromCommandLine) { this.isJWS = isJWS; _logger = logger; this.mainClassFromCommandLine = mainClassFromCommandLine; } protected void setDescriptor(ApplicationClientDescriptor acDesc) { this.acDesc = acDesc; } protected ApplicationClientDescriptor getDescriptor() { return acDesc; } protected void completeInit() throws Exception { } // /** // *Finishes initialization work. // *

// *The calling logic that instantiates this object must invoke completeInit // *after instantiation but before using the object. // *@throws IOException for errors opening the expanded archive // *@throws SAXParseException for errors parsing the descriptors in a newly-opened archive // *@throws ClassNotFoundException if the main class requested cannot be located in the archive // *@throws URISyntaxException if preparing URIs for the class loader fails // * // */ // protected void completeInit(URL[] persistenceURLs) // throws IOException, SAXParseException, ClassNotFoundException, // URISyntaxException, AnnotationProcessorException, Exception { // // //expand if needed. initialize the appClientArchive //// appClientArchive = expand(appClientArchive); // // //Create the class loader to be used for persistence unit checking, // //validation, and running the app client. // classLoader = createClassLoader(appClientArchive, persistenceURLs); // // //Populate the deployment descriptor without validation. // //Note that validation is done only after the persistence handling // //has instructed the classloader created above. // populateDescriptor(appClientArchive, archivist, classLoader); // // //If the selected app client depends on at least one persistence unit // //then handle the P.U. before proceeding. // if (appClientDependsOnPersistenceUnit(getAppClient())) { // //@@@check to see if the descriptor is metadata-complet=true // //if not, we would have loaded classes into the classloader // //during annotation processing. we need to hault and ask // //the user to deploy the application. // //if (!getAppClient().isFullFlag()) { // // throw new RuntimeException("Please deploy your application"); // //} // handlePersistenceUnitDependency(); // } // // //Now that the persistence handling has run and instrumented the class // //loader - if it had to - it's ok to validate. // archivist.validate(classLoader); // // fixupWSDLEntries(); // // if (isJWS) { // grantRequestedPermissionsToUserCode(); // } // } /** *Returns the app client descriptor to be run. *@return the descriptor for the selected app client */ protected ApplicationClientDescriptor getAppClient() { return getAppClient(archivist); } protected ClassLoader getClassLoader() { return classLoader; } protected void close() throws IOException { } protected boolean deleteAppClientDir() { return !_keepExplodedDir; } protected String getLocalString(final String key, final String defaultMessage, final Object... args) { String result = localStrings.getLocalString(this.getClass(), key, defaultMessage, args); return result; } /** *Processes persistence unit handling for the ACC. */ protected void handlePersistenceUnitDependency() throws URISyntaxException, MalformedURLException { // XXX Mitesh helping to update this // this.puAppInfo = new ApplicationInfoImpl(this); // new PersistenceUnitLoaderImpl().load(puAppInfo); } /** * implementation of * {@link com.sun.enterprise.server.PersistenceUnitLoader.ApplicationInfo}. */ private static class ApplicationInfoImpl // XXX Mitesh helping to update this // implements PersistenceUnitLoader.ApplicationInfo { private AppClientInfo outer; // the outer object we are associated with private ApplicationClientDescriptor appClient; public ApplicationInfoImpl(AppClientInfo outer) { this.outer = outer; appClient = outer.getAppClient(); } //TODO: This method does not appear to be used -- can it be deleted? public Application getApplication(ServiceLocator habitat) { Application application = appClient.getApplication(); if (application == null) { application = Application.createVirtualApplication( appClient.getModuleID(), appClient.getModuleDescriptor()); } return application; } public InstrumentableClassLoader getClassLoader() { return (InstrumentableClassLoader) outer.getClassLoader(); } // public String getApplicationLocation() { // return outer.appClientArchive.getURI().toASCIIString(); // } /** * @return list of PU that are actually referenced by the * appclient. */ public Collection getReferencedPUs() { return appClient.findReferencedPUs(); } /** * @return list of EMFs that have been loaded for this appclient. */ public Collection getEntityManagerFactories() { Collection emfs = new HashSet(); if (appClient.getApplication() != null) { emfs.addAll(appClient.getApplication() .getEntityManagerFactories()); } emfs.addAll(appClient.getEntityManagerFactories()); return emfs; } } // end of class ApplicationInfoImpl /** *Reports whether the app client's descriptor shows a dependence on a *persistence unit. *@param descr the descriptor for the app client in question *@returns true if the descriptor shows such a dependency */ protected boolean descriptorContainsPURefcs( ApplicationClientDescriptor descr) { return ! descr.getEntityManagerFactoryReferenceDescriptors().isEmpty(); } /** *Reports whether the main class in the archive contains annotations that *refer to persistence units. *@return boolean if the main class contains annotations that refer to a pers. unit */ protected static URL getEntryAsUrl(File moduleLocation, String uri) throws MalformedURLException, IOException { URL url = null; try { url = new URL(uri); } catch(java.net.MalformedURLException e) { // ignore url = null; } if (url!=null) { return url; } if( moduleLocation != null ) { if( moduleLocation.isFile() ) { url = createJarUrl(moduleLocation, uri); } else { String path = uri.replace('/', File.separatorChar); url = new File(moduleLocation, path).toURI().toURL(); } } return url; } private static URL createJarUrl(File jarFile, String entry) throws MalformedURLException, IOException { return new URL("jar:" + jarFile.toURI().toURL() + "!/" + entry); } // XXX restore or move elsewhere -- grants permissions to jars expanded from v2 generated JAR // /** // *Granting the appropriate level of permissions to user code, emulating // *the Java Web Start behavior as required in the JNLP spec. // *

// *Classes from the user's app client jar are loaded using the ASURLClassLoader // *rather than the Java Web Start class loader. As a result, Java Web Start // *cannot grant the appropriate level of permissions to the user code since // *it is the JWS class loader that does that. So we need to grant the user // *code the appropriate level of permissions, based on whether the user's // *app client jar was signed or not. // *@param retainTempFiles indicates whether to keep the generated policy file // */ // protected void grantRequestedPermissionsToUserCode() throws IOException, URISyntaxException { // /* // *Create a temporary file containing permissions grants. We will use // *this temp file to refresh the Policy objects's settings. The temp // *file will contain one segment for each element in the class path // *for the user code (from the expanded generated app client jar). // *The permissions granted will be the same for all class path elements, // *and the specific settings will either be the sandbox permissions // *as described in the JNLP spec or full permissions. // */ // boolean userJarIsSigned = Boolean.getBoolean(USER_CODE_IS_SIGNED_PROPERTYNAME); // // boolean retainTempFiles = Boolean.getBoolean(AppClientContainer.APPCLIENT_RETAIN_TEMP_FILES_PROPERTYNAME); // // /* // *Use a template to construct each part of the policy file, choosing the // *template based on whether the user code is signed or not. // */ // String templateName = (userJarIsSigned ? SIGNED_USER_CODE_PERMISSION_TEMPLATE_NAME : UNSIGNED_USER_CODE_PERMISSION_TEMPLATE_NAME); // String template = Util.loadResource(JWSACCMain.class, templateName); // // /* // *Create the temporary policy file to write to. // */ // File policyFile = File.createTempFile("accjws-user", ".policy"); // if ( ! retainTempFiles) { // policyFile.deleteOnExit(); // } // // PrintStream ps = null; // // try { // ps = new PrintStream(policyFile); // // Properties p = new Properties(); // // /* // *Use the list of class paths already set up on the ASURLClassLoader. // *Then for each element in the class path, write a part of the policy // *file granting the privs specified in the selected template to the code path. // */ // ASURLClassLoader loader = (ASURLClassLoader) getClassLoader(); // for (URL classPathElement : loader.getURLs()) { // /* // *Convert the URL into a proper codebase expression suitable for // *a grant clause in the policy file. // */ // String codeBase = Util.URLtoCodeBase(classPathElement); // if (codeBase != null) { // p.setProperty(CODE_BASE_PLACEHOLDER_NAME, codeBase); // String policyPart = Util.replaceTokens(template, p); // // ps.println(policyPart); // } // } // // /* // *Close the temp file and use it to refresh the current Policy object. // */ // ps.close(); // // JWSACCMain.refreshPolicy(policyFile); // // if ( ! retainTempFiles) { // policyFile.delete(); // } // } finally { // if (ps != null) { // ps.close(); // } // } // } ///////////////////////////////////////////////////////////////// // The following protected methods are overridden by at least // // one of the sub classes. // ///////////////////////////////////////////////////////////////// // /** // *Expands the contents of the source archive into a temporary // *directory, using the same format as backend server expansions. // *@param file an archive file to be expanded // *@return an opened archive for the expanded directory archive // *@exception IOException in case of errors during the expansion // */ // protected abstract ReadableArchive expand(File file) // throws IOException, Exception; protected ApplicationClientDescriptor getAppClient( Archivist archivist) { return ApplicationClientDescriptor.class.cast( archivist.getDescriptor()); } protected String getAppClientRoot( ReadableArchive archive, ApplicationClientDescriptor descriptor) { return archive.getURI().toASCIIString(); } protected void massageDescriptor() throws IOException, AnnotationProcessorException { //default behavor: no op } protected List getClassPaths(ReadableArchive archive) { List paths = new ArrayList(); paths.add(archive.getURI().toASCIIString()); return paths; } /** *Returns the main class that should be executed. *@return the name of the main class to execute when the client starts */ protected String getMainClassNameToRun(ApplicationClientDescriptor acDescr) { if (mainClassNameToRun == null) { if (mainClassFromCommandLine != null) { mainClassNameToRun = mainClassFromCommandLine; _logger.fine("Main class is " + mainClassNameToRun + " from command line"); } else { /* *Find out which class to execute from the descriptor. */ mainClassNameToRun = getAppClient().getMainClassName(); _logger.fine("Main class is " + mainClassNameToRun + " from descriptor"); } } return mainClassNameToRun; } protected boolean classContainsAnnotation( String entry, AnnotationDetector detector, ReadableArchive archive, ApplicationClientDescriptor descriptor) throws FileNotFoundException, IOException { return detector.containsAnnotation(archive, entry); // String acRoot = getAppClientRoot(archive, descriptor); // String entryLocation = acRoot + File.separator + entry; // File entryFile = new File(entryLocation); // return detector.containsAnnotation(archive, entry) // return detector.containsAnnotation(entryFile); } @Override public String toString() { String lineSep = System.getProperty("line.separator"); StringBuilder result = new StringBuilder(); result.append(this.getClass().getName() + ": " + lineSep); result.append(" isJWS: " + isJWS); // result.append(" archive file: " + appClientArchive.getURI().toASCIIString() + lineSep); // result.append(" archive type: " + appClientArchive.getClass().getName() + lineSep); result.append(" archivist type: " + archivist.getClass().getName() + lineSep); result.append(" main class to be run: " + mainClassNameToRun + lineSep); // result.append(" temporary archive directory: " + appClientArchive.getURI() + lineSep); result.append(" class loader type: " + classLoader.getClass().getName() + lineSep); return result.toString(); } //for debug purpose protected static final boolean _keepExplodedDir = Boolean.getBoolean("appclient.keep.exploded.dir"); }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy