| /******************************************************************************* |
| * Copyright (c) 2003, 2016 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.osgi.framework.util; |
| |
| import java.io.*; |
| import java.net.*; |
| import java.security.*; |
| import java.util.Properties; |
| import java.util.zip.ZipException; |
| import java.util.zip.ZipFile; |
| import org.eclipse.osgi.container.Module; |
| import org.osgi.framework.*; |
| import org.osgi.util.tracker.ServiceTracker; |
| |
| /** |
| * Utility class to execute common privileged code. |
| * @since 3.1 |
| */ |
| public class SecureAction { |
| // make sure we use the correct controlContext; |
| private AccessControlContext controlContext; |
| |
| // This ClassLoader is used in loadSystemClass if System.getClassLoader() returns null |
| static final ClassLoader bootClassLoader = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() { |
| @Override |
| public ClassLoader run() { |
| return new ClassLoader(Object.class.getClassLoader()) { /* boot class loader */}; |
| } |
| }); |
| |
| /* |
| * Package privaet constructor a new SecureAction object. |
| * The constructed SecureAction object uses the caller's AccessControlContext |
| * to perform security checks |
| */ |
| SecureAction() { |
| // save the control context to be used. |
| this.controlContext = AccessController.getContext(); |
| } |
| |
| /** |
| * Creates a privileged action that can be used to construct a SecureAction object. |
| * The recommended way to construct a SecureAction object is the following: <p> |
| * <pre> |
| * SecureAction secureAction = (SecureAction) AccessController.doPrivileged(SecureAction.createSecureAction()); |
| * </pre> |
| * @return a privileged action object that can be used to construct a SecureAction object. |
| */ |
| public static PrivilegedAction<SecureAction> createSecureAction() { |
| return new PrivilegedAction<SecureAction>() { |
| @Override |
| public SecureAction run() { |
| return new SecureAction(); |
| } |
| }; |
| } |
| |
| /** |
| * Returns a system property. Same as calling |
| * System.getProperty(String). |
| * @param property the property key. |
| * @return the value of the property or null if it does not exist. |
| */ |
| public String getProperty(final String property) { |
| if (System.getSecurityManager() == null) |
| return System.getProperty(property); |
| return AccessController.doPrivileged(new PrivilegedAction<String>() { |
| @Override |
| public String run() { |
| return System.getProperty(property); |
| } |
| }, controlContext); |
| } |
| |
| /** |
| * Returns a system properties. Same as calling |
| * System.getProperties(). |
| * @return the system properties. |
| */ |
| public Properties getProperties() { |
| if (System.getSecurityManager() == null) |
| return System.getProperties(); |
| return AccessController.doPrivileged(new PrivilegedAction<Properties>() { |
| @Override |
| public Properties run() { |
| return System.getProperties(); |
| } |
| }, controlContext); |
| } |
| |
| /** |
| * Creates a FileInputStream from a File. Same as calling |
| * new FileInputStream(File). |
| * @param file the File to craete a FileInputStream from. |
| * @return The FileInputStream. |
| * @throws FileNotFoundException if the File does not exist. |
| */ |
| public FileInputStream getFileInputStream(final File file) throws FileNotFoundException { |
| if (System.getSecurityManager() == null) |
| return new FileInputStream(file); |
| try { |
| return AccessController.doPrivileged(new PrivilegedExceptionAction<FileInputStream>() { |
| @Override |
| public FileInputStream run() throws FileNotFoundException { |
| return new FileInputStream(file); |
| } |
| }, controlContext); |
| } catch (PrivilegedActionException e) { |
| if (e.getException() instanceof FileNotFoundException) |
| throw (FileNotFoundException) e.getException(); |
| throw (RuntimeException) e.getException(); |
| } |
| } |
| |
| /** |
| * Creates a FileInputStream from a File. Same as calling |
| * new FileOutputStream(File,boolean). |
| * @param file the File to create a FileOutputStream from. |
| * @param append indicates if the OutputStream should append content. |
| * @return The FileOutputStream. |
| * @throws FileNotFoundException if the File does not exist. |
| */ |
| public FileOutputStream getFileOutputStream(final File file, final boolean append) throws FileNotFoundException { |
| if (System.getSecurityManager() == null) |
| return new FileOutputStream(file.getAbsolutePath(), append); |
| try { |
| return AccessController.doPrivileged(new PrivilegedExceptionAction<FileOutputStream>() { |
| @Override |
| public FileOutputStream run() throws FileNotFoundException { |
| return new FileOutputStream(file.getAbsolutePath(), append); |
| } |
| }, controlContext); |
| } catch (PrivilegedActionException e) { |
| if (e.getException() instanceof FileNotFoundException) |
| throw (FileNotFoundException) e.getException(); |
| throw (RuntimeException) e.getException(); |
| } |
| } |
| |
| /** |
| * Returns the length of a file. Same as calling |
| * file.length(). |
| * @param file a file object |
| * @return the length of a file. |
| */ |
| public long length(final File file) { |
| if (System.getSecurityManager() == null) |
| return file.length(); |
| return AccessController.doPrivileged(new PrivilegedAction<Long>() { |
| @Override |
| public Long run() { |
| return new Long(file.length()); |
| } |
| }, controlContext).longValue(); |
| } |
| |
| /** |
| * Returns the canonical path of a file. Same as calling |
| * file.getCanonicalPath(). |
| * @param file a file object |
| * @return the canonical path of a file. |
| * @throws IOException on error |
| */ |
| public String getCanonicalPath(final File file) throws IOException { |
| if (System.getSecurityManager() == null) |
| return file.getCanonicalPath(); |
| try { |
| return AccessController.doPrivileged(new PrivilegedExceptionAction<String>() { |
| @Override |
| public String run() throws IOException { |
| return file.getCanonicalPath(); |
| } |
| }, controlContext); |
| } catch (PrivilegedActionException e) { |
| if (e.getException() instanceof IOException) |
| throw (IOException) e.getException(); |
| throw (RuntimeException) e.getException(); |
| } |
| } |
| |
| /** |
| * Returns the absolute file. Same as calling |
| * file.getAbsoluteFile(). |
| * @param file a file object |
| * @return the absolute file. |
| */ |
| public File getAbsoluteFile(final File file) { |
| if (System.getSecurityManager() == null) |
| return file.getAbsoluteFile(); |
| return AccessController.doPrivileged(new PrivilegedAction<File>() { |
| @Override |
| public File run() { |
| return file.getAbsoluteFile(); |
| } |
| }, controlContext); |
| } |
| |
| /** |
| * Returns the canonical file. Same as calling |
| * file.getCanonicalFile(). |
| * @param file a file object |
| * @return the canonical file. |
| */ |
| public File getCanonicalFile(final File file) throws IOException { |
| if (System.getSecurityManager() == null) |
| return file.getCanonicalFile(); |
| try { |
| return AccessController.doPrivileged(new PrivilegedExceptionAction<File>() { |
| @Override |
| public File run() throws IOException { |
| return file.getCanonicalFile(); |
| } |
| }, controlContext); |
| } catch (PrivilegedActionException e) { |
| if (e.getException() instanceof IOException) |
| throw (IOException) e.getException(); |
| throw (RuntimeException) e.getException(); |
| } |
| } |
| |
| /** |
| * Returns true if a file exists, otherwise false is returned. Same as calling |
| * file.exists(). |
| * @param file a file object |
| * @return true if a file exists, otherwise false |
| */ |
| public boolean exists(final File file) { |
| if (System.getSecurityManager() == null) |
| return file.exists(); |
| return AccessController.doPrivileged(new PrivilegedAction<Boolean>() { |
| @Override |
| public Boolean run() { |
| return file.exists() ? Boolean.TRUE : Boolean.FALSE; |
| } |
| }, controlContext).booleanValue(); |
| } |
| |
| public boolean mkdirs(final File file) { |
| if (System.getSecurityManager() == null) |
| return file.mkdirs(); |
| return AccessController.doPrivileged(new PrivilegedAction<Boolean>() { |
| @Override |
| public Boolean run() { |
| return file.mkdirs() ? Boolean.TRUE : Boolean.FALSE; |
| } |
| }, controlContext).booleanValue(); |
| } |
| |
| /** |
| * Returns true if a file is a directory, otherwise false is returned. Same as calling |
| * file.isDirectory(). |
| * @param file a file object |
| * @return true if a file is a directory, otherwise false |
| */ |
| public boolean isDirectory(final File file) { |
| if (System.getSecurityManager() == null) |
| return file.isDirectory(); |
| return AccessController.doPrivileged(new PrivilegedAction<Boolean>() { |
| @Override |
| public Boolean run() { |
| return file.isDirectory() ? Boolean.TRUE : Boolean.FALSE; |
| } |
| }, controlContext).booleanValue(); |
| } |
| |
| /** |
| * Returns a file's last modified stamp. Same as calling |
| * file.lastModified(). |
| * @param file a file object |
| * @return a file's last modified stamp. |
| */ |
| public long lastModified(final File file) { |
| if (System.getSecurityManager() == null) |
| return file.lastModified(); |
| return AccessController.doPrivileged(new PrivilegedAction<Long>() { |
| @Override |
| public Long run() { |
| return new Long(file.lastModified()); |
| } |
| }, controlContext).longValue(); |
| } |
| |
| /** |
| * Returns a file's list. Same as calling |
| * file.list(). |
| * @param file a file object |
| * @return a file's list. |
| */ |
| public String[] list(final File file) { |
| if (System.getSecurityManager() == null) |
| return file.list(); |
| return AccessController.doPrivileged(new PrivilegedAction<String[]>() { |
| @Override |
| public String[] run() { |
| return file.list(); |
| } |
| }, controlContext); |
| } |
| |
| /** |
| * Returns a ZipFile. Same as calling |
| * new ZipFile(file) |
| * @param file the file to get a ZipFile for |
| * @return a ZipFile |
| * @throws IOException if an error occured |
| */ |
| public ZipFile getZipFile(final File file) throws IOException { |
| try { |
| if (System.getSecurityManager() == null) |
| return new ZipFile(file); |
| try { |
| return AccessController.doPrivileged(new PrivilegedExceptionAction<ZipFile>() { |
| @Override |
| public ZipFile run() throws IOException { |
| return new ZipFile(file); |
| } |
| }, controlContext); |
| } catch (PrivilegedActionException e) { |
| if (e.getException() instanceof IOException) |
| throw (IOException) e.getException(); |
| throw (RuntimeException) e.getException(); |
| } |
| } catch (ZipException e) { |
| ZipException zipNameException = new ZipException("Exception in opening zip file: " + file.getPath()); //$NON-NLS-1$ |
| zipNameException.initCause(e); |
| throw zipNameException; |
| } catch (IOException e) { |
| throw new IOException("Exception in opening zip file: " + file.getPath(), e); //$NON-NLS-1$ |
| } |
| } |
| |
| /** |
| * Gets a URL. Same a calling |
| * {@link URL#URL(java.lang.String, java.lang.String, int, java.lang.String, java.net.URLStreamHandler)} |
| * @param protocol the protocol |
| * @param host the host |
| * @param port the port |
| * @param file the file |
| * @param handler the URLStreamHandler |
| * @return a URL |
| * @throws MalformedURLException |
| */ |
| public URL getURL(final String protocol, final String host, final int port, final String file, final URLStreamHandler handler) throws MalformedURLException { |
| if (System.getSecurityManager() == null) |
| return new URL(protocol, host, port, file, handler); |
| try { |
| return AccessController.doPrivileged(new PrivilegedExceptionAction<URL>() { |
| @Override |
| public URL run() throws MalformedURLException { |
| return new URL(protocol, host, port, file, handler); |
| } |
| }, controlContext); |
| } catch (PrivilegedActionException e) { |
| if (e.getException() instanceof MalformedURLException) |
| throw (MalformedURLException) e.getException(); |
| throw (RuntimeException) e.getException(); |
| } |
| } |
| |
| /** |
| * Creates a new Thread from a Runnable. Same as calling |
| * new Thread(target,name).setContextClassLoader(contextLoader). |
| * @param target the Runnable to create the Thread from. |
| * @param name The name of the Thread. |
| * @param contextLoader the context class loader for the thread |
| * @return The new Thread |
| */ |
| public Thread createThread(final Runnable target, final String name, final ClassLoader contextLoader) { |
| if (System.getSecurityManager() == null) |
| return createThread0(target, name, contextLoader); |
| return AccessController.doPrivileged(new PrivilegedAction<Thread>() { |
| @Override |
| public Thread run() { |
| return createThread0(target, name, contextLoader); |
| } |
| }, controlContext); |
| } |
| |
| Thread createThread0(Runnable target, String name, ClassLoader contextLoader) { |
| Thread result = new Thread(target, name); |
| if (contextLoader != null) |
| result.setContextClassLoader(contextLoader); |
| return result; |
| } |
| |
| /** |
| * Gets a service object. Same as calling |
| * context.getService(reference) |
| * @param reference the ServiceReference |
| * @param context the BundleContext |
| * @return a service object |
| */ |
| public <S> S getService(final ServiceReference<S> reference, final BundleContext context) { |
| if (System.getSecurityManager() == null) |
| return context.getService(reference); |
| return AccessController.doPrivileged(new PrivilegedAction<S>() { |
| @Override |
| public S run() { |
| return context.getService(reference); |
| } |
| }, controlContext); |
| } |
| |
| /** |
| * Returns a Class. Same as calling |
| * Class.forName(name) |
| * @param name the name of the class. |
| * @return a Class |
| * @throws ClassNotFoundException |
| */ |
| public Class<?> forName(final String name) throws ClassNotFoundException { |
| if (System.getSecurityManager() == null) |
| return Class.forName(name); |
| try { |
| return AccessController.doPrivileged(new PrivilegedExceptionAction<Class<?>>() { |
| @Override |
| public Class<?> run() throws Exception { |
| return Class.forName(name); |
| } |
| }, controlContext); |
| } catch (PrivilegedActionException e) { |
| if (e.getException() instanceof ClassNotFoundException) |
| throw (ClassNotFoundException) e.getException(); |
| throw (RuntimeException) e.getException(); |
| } |
| } |
| |
| /** |
| * Returns a Class. |
| * Tries to load a class from the System ClassLoader or if that doesn't exist tries the boot ClassLoader |
| * @param name the name of the class. |
| * @return a Class |
| * @throws ClassNotFoundException |
| */ |
| public Class<?> loadSystemClass(final String name) throws ClassNotFoundException { |
| if (System.getSecurityManager() == null) { |
| ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); |
| return (systemClassLoader != null) ? systemClassLoader.loadClass(name) : bootClassLoader.loadClass(name); |
| } |
| try { |
| return AccessController.doPrivileged(new PrivilegedExceptionAction<Class<?>>() { |
| @Override |
| public Class<?> run() throws Exception { |
| ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); |
| return (systemClassLoader != null) ? systemClassLoader.loadClass(name) : bootClassLoader.loadClass(name); |
| } |
| }, controlContext); |
| } catch (PrivilegedActionException e) { |
| if (e.getException() instanceof ClassNotFoundException) |
| throw (ClassNotFoundException) e.getException(); |
| throw (RuntimeException) e.getException(); |
| } |
| } |
| |
| /** |
| * Opens a ServiceTracker. Same as calling tracker.open() |
| * @param tracker the ServiceTracker to open. |
| */ |
| public void open(final ServiceTracker<?, ?> tracker) { |
| if (System.getSecurityManager() == null) { |
| tracker.open(); |
| return; |
| } |
| AccessController.doPrivileged(new PrivilegedAction<Void>() { |
| @Override |
| public Void run() { |
| tracker.open(); |
| return null; |
| } |
| }, controlContext); |
| } |
| |
| /** |
| * Starts a module. |
| * @param module the module to start |
| * @param options the start options |
| * @throws BundleException |
| */ |
| public void start(final Module module, final Module.StartOptions... options) throws BundleException { |
| if (System.getSecurityManager() == null) { |
| module.start(options); |
| return; |
| } |
| try { |
| AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() { |
| @Override |
| public Void run() throws BundleException { |
| module.start(options); |
| return null; |
| } |
| }, controlContext); |
| return; |
| } catch (PrivilegedActionException e) { |
| if (e.getException() instanceof BundleException) |
| throw (BundleException) e.getException(); |
| throw (RuntimeException) e.getException(); |
| } |
| } |
| |
| public BundleContext getContext(final Bundle bundle) { |
| if (System.getSecurityManager() == null) { |
| return bundle.getBundleContext(); |
| } |
| return AccessController.doPrivileged(new PrivilegedAction<BundleContext>() { |
| @Override |
| public BundleContext run() { |
| return bundle.getBundleContext(); |
| } |
| }, controlContext); |
| } |
| |
| public String getLocation(final Bundle bundle) { |
| if (System.getSecurityManager() == null) { |
| return bundle.getLocation(); |
| } |
| return AccessController.doPrivileged(new PrivilegedAction<String>() { |
| @Override |
| public String run() { |
| return bundle.getLocation(); |
| } |
| }, controlContext); |
| } |
| } |