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

com.google.apphosting.runtime.NullSandboxPlugin Maven / Gradle / Ivy

There is a newer version: 2.0.32
Show newest version
/*
 * Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.apphosting.runtime;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Plugin for the "null" Java sandbox.
 *
 * 

This sandbox does not enforce any special checks and uses a plain * {@link URLClassLoader} to load the runtime classes. */ public class NullSandboxPlugin { private static final Logger rootLogger = Logger.getLogger(""); static final String ALWAYS_SCAN_CLASS_DIRS_PROPERTY = "com.google.appengine.always.scan.class.dirs"; private volatile ClassLoader runtimeLoader; private volatile ClassLoader applicationLoader; private volatile ClassPathUtils classPathUtils; /** * Class loader used to load classes that are shared between the runtime * and the application, e.g. the java.servlet API and the ApiProxy class. */ private ClassLoader sharedClassLoader; public NullSandboxPlugin() { } /** * For unit tests only. Use of this constructor precludes calling * {@code createRuntimeClassLoader}. */ public NullSandboxPlugin( ClassLoader runtimeLoader, ClassLoader sharedLoader, ClassPathUtils classPathUtils) { this.sharedClassLoader = sharedLoader; this.classPathUtils = classPathUtils; this.runtimeLoader = runtimeLoader; } /** * Creates a {@code ClassLoader} suitable to load the runtime from. * * @param classPathUtils a ClassPathUtils object configured according to the command-line * arguments passed to the main class * @param appsRoot path to the base directory for applications * @return a runtime ClassLoader * @throws IllegalStateException if this method has been called once already */ public ClassLoader createRuntimeClassLoader(ClassPathUtils classPathUtils, String appsRoot) { if (runtimeLoader != null) { throw new IllegalStateException("createRuntimeClassLoader already called"); } ClassLoader loader = doCreateRuntimeClassLoader(classPathUtils, appsRoot); this.classPathUtils = classPathUtils; this.runtimeLoader = loader; return loader; } /** * Creates a {@code URLClassLoader} suitable to load the runtime from. * * @param classPathUtils a ClassPathUtils object configured according to the command-line * arguments passed to the main class * @param appsRoot path to the base directory for applications * @return a runtime ClassLoader */ protected ClassLoader doCreateRuntimeClassLoader(ClassPathUtils classPathUtils, String appsRoot) { sharedClassLoader = new URLClassLoader(classPathUtils.getRuntimeSharedUrls()); return new URLClassLoader(classPathUtils.getRuntimeImplUrls(), sharedClassLoader); } /** Returns the app classloader. */ public ClassLoader getApplicationClassLoader() { checkApplicationClassLoader(); return applicationLoader; } /** * Creates a {@code ClassLoader} for application code. * * @param userUrls the URLs comprising all user application code * @param contextRoot the root for the user's application * @param environment the process environment for the application * @return a user URLClassLoader * @throws IllegalStateException if createRuntimeClassLoader wasn't called or didn't * complete successfully */ public ClassLoader createApplicationClassLoader( URL[] userUrls, File contextRoot, ApplicationEnvironment environment) { checkRuntimeClassLoader(); ClassLoader loader = doCreateApplicationClassLoader(userUrls, contextRoot, environment); this.applicationLoader = loader; return loader; } /** * Creates a {@code ClassLoader} for application code. * * @param userUrls the URLs comprising all user application code * @param contextRoot the root for the user's application * @param environment the process environment for the application * @return a user ClassLoader */ protected ClassLoader doCreateApplicationClassLoader( URL[] userUrls, File contextRoot, ApplicationEnvironment environment) { // Add prebundled jars at the end of the application class path. This code and its helper // methods were copied from UserClassLoaderFactory.createClassLoader. URL[] prebundledUrls = getClassPathUtils().getPrebundledUrls(); userUrls = append(userUrls, prebundledUrls); // Add the j-connector class path at the front. Also copied from // UserClassLoaderFactory.createClassLoader. if (environment.getRuntimeConfiguration().getCloudSqlJdbcConnectivityEnabled() && environment.getUseGoogleConnectorJ()) { URL[] urls = getClassPathUtils().getConnectorJUrls(); userUrls = append(urls, userUrls); } URL[] legacyUrls = getClassPathUtils().getLegacyJarUrls(); boolean alwaysScanClassDirs = "true".equalsIgnoreCase( environment.getSystemProperties().get(ALWAYS_SCAN_CLASS_DIRS_PROPERTY)); return new ApplicationClassLoader( userUrls, legacyUrls, sharedClassLoader, alwaysScanClassDirs); } /** * Returns the {@code ClassPathUtils} object used to create the runtime class loader. * *

This method MUST be called after {@link #createRuntimeClassLoader}. * * @return the ClassPathUtils associated with the runtime class loader * @throws IllegalStateException if createRuntimeClassLoader wasn't called or didn't * complete successfully */ public ClassPathUtils getClassPathUtils() { checkRuntimeClassLoader(); return classPathUtils; } /** * Verifies that the runtime classloader was created. * @throws IllegalStateException otherwise */ private void checkRuntimeClassLoader() { if (runtimeLoader == null) { throw new IllegalStateException("must call createRuntimeClassLoader first"); } } /** * Verifies that the application classloader was created. * @throws IllegalStateException otherwise */ private void checkApplicationClassLoader() { if (applicationLoader == null) { throw new IllegalStateException("must call createApplicationClassLoader first"); } } private static T[] append(T[] first, T[] second) { T[] newArray = Arrays.copyOf(first, first.length + second.length); System.arraycopy(second, 0, newArray, first.length, second.length); return newArray; } /** Starts re-routing application logs through the ApiProxy. */ public void startCapturingApplicationLogs() { // We need to load the appropriate log handler using the runtime class loader // because it depends on the ApiProxy class, which is not accessible to code loaded // by the system class loader. try { Class handlerClass = Class.forName("com.google.apphosting.runtime.NullSandboxLogHandler", true, runtimeLoader); Object logHandler = handlerClass.getDeclaredConstructor().newInstance(); Method m = handlerClass.getMethod("init", Logger.class); m.invoke(logHandler, rootLogger); } catch (ReflectiveOperationException e) { throw new RuntimeException("failed to install the LogHandler for application logs", e); } } /** Changes the current directory. */ public static void chdir(String path) throws IOException { try { chdir0(path); } catch (UnsatisfiedLinkError e) { Logger.getLogger(NullSandboxPlugin.class.getName()) .log(Level.WARNING, "Could not call native chdir", e); } } private static native void chdir0(String path) throws IOException; }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy