Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ public class CLIBootstrap {

static final String ENV_VAR_PROP_PREFIX = "acc.";


private final static String SECURITY_AUTH_LOGIN_CONFIG_PROPERTY_EXPR = "-Djava.security.auth.login.config=";
private final static String SYSPROP_SYSTEM_CLASS_LOADER = "-Djava.system.class.loader=";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024, 2025 Contributors to the Eclipse Foundation
* Copyright (c) 2024, 2026 Contributors to the Eclipse Foundation
* Copyright (c) 1997, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
Expand Down Expand Up @@ -35,7 +35,6 @@
import javax.swing.SwingUtilities;

import org.glassfish.appclient.client.jws.boot.ErrorDisplayDialog;
import org.glassfish.appclient.client.jws.boot.LaunchSecurityHelper;
import org.glassfish.embeddable.client.UserError;

/**
Expand Down Expand Up @@ -93,7 +92,6 @@ public static void main(String[] args) {
processJWSArgs();

final String agentArgsText = System.getProperty("agent.args");
LaunchSecurityHelper.setPermissions();

// Prevent the Java Web Start class loader from delegating to its parent when resolving
// classes and resources that should come from the GlassFish-provided endorsed JARs.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2025 Contributors to the Eclipse Foundation
* Copyright (c) 2022, 2026 Contributors to the Eclipse Foundation
* Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
Expand All @@ -17,29 +17,14 @@

package org.glassfish.appclient.client.jws.boot;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.security.Policy;
import java.text.MessageFormat;
import java.util.ResourceBundle;
import java.util.Vector;

import javax.swing.SwingUtilities;

import org.glassfish.appclient.client.acc.AppClientContainer;
import org.glassfish.main.jdke.cl.GlassfishUrlClassLoader;

import static org.glassfish.main.jdke.props.SystemProperties.setProperty;
Expand All @@ -62,12 +47,6 @@
*/
public class JWSACCMain implements Runnable {

/** name of the permissions template */
private static final String PERMISSIONS_TEMPLATE_NAME = "jwsclient.policy";

/** placeholder used in the policy template to substitute dynamically-generated grant clauses */
private static final String GRANT_CLAUSES_PROPERTY_EXPR = "${grant.clauses}";

/** unpublished command-line argument conveying jwsacc information */
private static final String JWSACC_ARGUMENT_PREFIX = "-jwsacc";

Expand All @@ -79,11 +58,6 @@ public class JWSACCMain implements Runnable {

private static final String JWSACC_RUN_ON_SWING_THREAD = "RunOnSwingThread";

/** grant clause template for dynamically populating the policy */
private static final String GRANT_CLAUSE_TEMPLATE = "grant codeBase \"{0}\" '{'\n" +
" permission java.security.AllPermission;\n" +
"'}';";

/**
* request to exit the JVM upon return from the client - should be set (via
* the -jwsacc command-line argument value) only for
Expand Down Expand Up @@ -138,12 +112,6 @@ public static void main(String[] args) {
throw new IllegalArgumentException(rb.getString("jwsacc.errorLocJARs"), thr);
}

/*
*Before creating the new instance of the real ACC main, set permissions
*so ACC and the user's app client can function properly.
*/
setPermissions();

/*
*Make sure that the main ACC class is instantiated and run in the
*same thread. Java Web Start may not normally do so.
Expand Down Expand Up @@ -171,7 +139,6 @@ private static String dotToSlash(String orig) {

@Override
public void run() {
// Main.main(args);
int exitValue = 0;
try {
File downloadedAppclientJarFile = findAppClientFileForJWSLaunch(getClass().getClassLoader());
Expand Down Expand Up @@ -257,8 +224,9 @@ private static String[] prepareJWSArgs(String[] args) {
}

/**
*Interpret the JWSACC arguments (if any) supplied on the command line.
*@param args the JWSACC arguments
* Interpret the JWSACC arguments (if any) supplied on the command line.
*
* @param args the JWSACC arguments
*/
private static void processJWSArgs(Vector<String> args) {
for (String arg : args) {
Expand All @@ -274,133 +242,57 @@ private static void processJWSArgs(Vector<String> args) {
}
}

private static void setPermissions() {
try {
/*
*/
String permissionsTemplate = loadResource(JWSACCMain.class, PERMISSIONS_TEMPLATE_NAME);

/*
*Prepare the grant clauses for the downloaded jars and substitute
*those clauses into the policy template.
*/
StringBuilder grantClauses = new StringBuilder();

for (URL url : downloadedJarURLs) {
grantClauses.append(MessageFormat.format(GRANT_CLAUSE_TEMPLATE, url.toExternalForm()));
}

for (URL url : persistenceJarURLs) {
grantClauses.append(MessageFormat.format(GRANT_CLAUSE_TEMPLATE, url.toExternalForm()));
}

String substitutedPermissionsTemplate = permissionsTemplate.replace(GRANT_CLAUSES_PROPERTY_EXPR, grantClauses.toString());
boolean retainTempFiles = Boolean.getBoolean(AppClientContainer.APPCLIENT_RETAIN_TEMP_FILES_PROPERTYNAME);
File policyFile = writeTextToTempFile(substitutedPermissionsTemplate, "jwsacc", ".policy", retainTempFiles);

refreshPolicy(policyFile);

} catch (IOException ioe) {
throw new RuntimeException("Error loading permissions template", ioe);
}
}

/**
*Locates the first free policy.url.x setting.
*@return the int value for the first unused policy setting
* Locates the first free policy.url.x setting.
*
* @return the int value for the first unused policy setting
*/
public static int firstFreePolicyIndex() {
int i = 0;
String propValue;
do {
propValue = java.security.Security.getProperty("policy.url." + String.valueOf(++i));
} while ((propValue != null) && ( ! propValue.equals("")));
} while ((propValue != null) && (!propValue.equals("")));

return i;
}

/**
*Refreshes the current policy object using the contents of the specified file
*as additional policy.
*@param policyFile the file containing additional policy
*/
public static void refreshPolicy(File policyFile) {
int idx = firstFreePolicyIndex();
URI policyFileURI = policyFile.toURI();
java.security.Security.setProperty("policy.url." + idx, policyFileURI.toASCIIString());
Policy p = Policy.getPolicy();
p.refresh();
}

/**
*The methods below are duplicates from the com.sun.enterprise.appclient.jws.Util class.
*At the time this class is running, Java Web Start will not yet permit the Util class to
*use the elevated permissions. In fact, this class is in the process of granting
*those permissions to all app server code. By including the code here, Java Web Start
*will permit it to run because this class was loaded from a trusted jar file.
*/

/**
*Writes the provided text to a temporary file marked for deletion on exit.
*@param the content to be written
*@param prefix for the temp file, conforming to the File.createTempFile requirements
*@param suffix for the temp file
*@return File object for the newly-created temp file
*@throws IOException for any errors writing the temporary file
*@throws FileNotFoundException if the temp file cannot be opened for any reason
*/
private static File writeTextToTempFile(String content, String prefix, String suffix, boolean retainTempFiles) throws IOException, FileNotFoundException {
BufferedWriter wtr = null;
try {
File result = File.createTempFile(prefix, suffix);
if ( ! retainTempFiles) {
result.deleteOnExit();
}
FileOutputStream fos = new FileOutputStream(result);
wtr = new BufferedWriter(new OutputStreamWriter(fos));
wtr.write(content);
wtr.close();
return result;
} finally {
if (wtr != null) {
wtr.close();
}
}
}

/**
*Create the class loader for loading code from the unsigned downloaded
*app server jars.
*<p>
*During a Java Web Start launch the ACC will be run under this class loader.
*Otherwise the JNLPClassLoader will load any stub classes that are
*packaged at the top-level of the generated app client jar file. (It can
*see them because it downloaded the gen'd app client jar, and therefore
*includes the downloaded jar in its class path. This allows it to see the
*classes at the top level of the jar but does not automatically let it see
*classes in the jars nested within the gen'd app client jar. As a result,
*the JNLPClassLoader would be the one to try to define the class for a
*web services stub, for instance. But the loader will not be able to find
*other classes and interfaces needed to completely define the class -
*because these are in the jars nested inside the gen'd app client jar. So
*the attempt to define the class would fail.
*@param downloadedAppclientJarFile the app client jar file
*@return the class loader
* Create the class loader for loading code from the unsigned downloaded
* app server jars.
* <p>
* During a Java Web Start launch the ACC will be run under this class loader.
* Otherwise the JNLPClassLoader will load any stub classes that are
* packaged at the top-level of the generated app client jar file. (It can
* see them because it downloaded the gen'd app client jar, and therefore
* includes the downloaded jar in its class path. This allows it to see the
* classes at the top level of the jar but does not automatically let it see
* classes in the jars nested within the gen'd app client jar. As a result,
* the JNLPClassLoader would be the one to try to define the class for a
* web services stub, for instance. But the loader will not be able to find
* other classes and interfaces needed to completely define the class -
* because these are in the jars nested inside the gen'd app client jar. So
* the attempt to define the class would fail.
*
* @param downloadedAppclientJarFile the app client jar file
* @return the class loader
*/
private static ClassLoader prepareClassLoader(File downloadedAppclientJarFile) throws IOException, URISyntaxException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
private static ClassLoader prepareClassLoader(File downloadedAppclientJarFile) {
return new GlassfishUrlClassLoader("JWS-ACC", downloadedJarURLs, classPathManager.getParentClassLoader());
}


/*
*Returns the jar that contains the specified resource.
*@param target entry name to look for
*@param loader the class loader to use in finding the resource
*@return File object for the jar or directory containing the entry
* Returns the jar that contains the specified resource.
* @param target entry name to look for
* @param loader the class loader to use in finding the resource
* @return File object for the jar or directory containing the entry
*/
private static File findContainingJar(String target, ClassLoader loader) throws IllegalArgumentException, URISyntaxException, MalformedURLException, IllegalAccessException, InvocationTargetException {
private static File findContainingJar(String target, ClassLoader loader) throws Exception {
File result = null;
/*
*Use the specified class loader to find the resource.
* Use the specified class loader to find the resource.
*/
URL resourceURL = loader.getResource(target);
if (resourceURL != null) {
Expand All @@ -409,24 +301,27 @@ private static File findContainingJar(String target, ClassLoader loader) throws
return result;
}


/**
*Locate the app client jar file during a Java Web Start launch.
*@param loader the class loader to use in searching for the descriptor entries
*@return File object for the client jar file
*@throws IllegalArgumentException if the loader finds neither descriptor
* Locate the app client jar file during a Java Web Start launch.
*
* @param loader the class loader to use in searching for the descriptor entries
* @return File object for the client jar file
* @throws Exception if the loader finds neither descriptor
*/
private File findAppClientFileForJWSLaunch(ClassLoader loader) throws URISyntaxException, MalformedURLException, IllegalAccessException, InvocationTargetException {
private File findAppClientFileForJWSLaunch(ClassLoader loader) throws Exception {
/*
*The downloaded jar should contain either META-INF/application.xml or
*META-INF/application-client.xml. Look for either one and locate the
*jar from the URL.
* The downloaded jar should contain either META-INF/application.xml or
* META-INF/application-client.xml. Look for either one and locate the
* jar from the URL.
*/
File containingJar = findContainingJar("META-INF/application.xml", loader);
if (containingJar == null) {
containingJar = findContainingJar("META-INF/application-client.xml", loader);
}
if (containingJar == null) {
throw new IllegalArgumentException("Could not locate META-INF/application.xml or META-INF/application-client.xml");
throw new IllegalArgumentException(
"Could not locate META-INF/application.xml or META-INF/application-client.xml");
}
return containingJar;
}
Expand All @@ -440,47 +335,4 @@ private File findAppClientFileForJWSLaunch(ClassLoader loader) throws URISyntaxE
public static ClassPathManager getClassPathManager() {
return ClassPathManager.getClassPathManager(keepJWSClassLoader);
}


/**
* Get the permissions template and write it to a temporary file.
*
* <p>
* This method does not save the template in a cache. Use the instance method
* getTemplate for that purpose.
*
* @param contextClass a class, the class loader of which should be used for searching for the template
* @param resourcePath the path of the resource to load, relative to the contextClass
* @return the resource's contents
* @throws IOException if the resource is not found or in case of error while loading it
*/
private static String loadResource(Class<?> contextClass, String resourcePath) throws IOException {
String result = null;
InputStream is = null;
BufferedReader reader = null;
try {
is = contextClass.getResourceAsStream(resourcePath);
if (is == null) {
throw new IOException("Could not locate the requested resource relative to class " + contextClass.getName());
}

StringBuilder sb = new StringBuilder();
reader = new BufferedReader(new InputStreamReader(is));
int charsRead;
char [] buffer = new char[1024];
while ((charsRead = reader.read(buffer)) != -1) {
sb.append(buffer, 0, charsRead);
}

result= sb.toString();
return result;
} catch (IOException ioe) {
throw new IOException("Error loading resource " + resourcePath, ioe);
} finally {
if (reader != null) {
reader.close();
}
}
}

}
Loading