blob: 962f625c48dbd1d39ab2f99475ddf899d38274a5 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 1997, 2018 by ProSyst Software GmbH
* http://www.prosyst.com
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* ProSyst Software GmbH - initial API and implementation
*******************************************************************************/
package org.eclipse.equinox.internal.util.security;
import java.io.*;
import java.util.Dictionary;
import org.eclipse.equinox.internal.util.UtilActivator;
import org.osgi.framework.*;
/**
* Utility class to execute common privileged code.
*
* @author Valentin Valchev
* @author Pavlin Dobrev
* @version 1.0
*/
public final class SecurityUtil implements PrivilegedRunner.PrivilegedDispatcher {
private Object controlContext;
private static final int SYSTEM_GET_PROPERTY = 41;
private static final int CREATE_THREAD = 42;
private static final int CLASS_FOR_NAME = 43;
private static final int SYSTEM_SET_PROPERTY = 44;
private static final int FILE_BASE = 50;
private static final int FILE_GET_INPUT_STREAM = FILE_BASE + 0;
private static final int FILE_GET_OUTPUT_STREAM = FILE_BASE + 1;
private static final int FILE_LENGTH = FILE_BASE + 2;
private static final int FILE_EXISTS = FILE_BASE + 3;
private static final int FILE_ISDIR = FILE_BASE + 4;
private static final int FILE_LAST_MODIFIED = FILE_BASE + 5;
private static final int FILE_LIST = FILE_BASE + 6;
private static final int FILE_DELETE = FILE_BASE + 7;
private static final int FILE_RENAME = FILE_BASE + 8;
private static final int FILE_GET_RANDOM_ACCESS_FILE = FILE_BASE + 9;
private static final int SERVICE_BASE = 60;
private static final int SERVICE_GET_REFERENCE = SERVICE_BASE + 0;
private static final int SERVICE_GET_SERVICE = SERVICE_BASE + 1;
private static final int SERVICE_REG_CLASS = SERVICE_BASE + 2;
private static final int SERVICE_REG_CLASSES = SERVICE_BASE + 3;
private static final int BUNDLE_BASE = 70;
private static final int BUNDLE_GET_LOCATION = BUNDLE_BASE + 0;
private static final int BUNDLE_GET_HEADERS = BUNDLE_BASE + 1;
private static final int BUNDLE_START = BUNDLE_BASE + 2;
private static final int BUNDLE_STOP = BUNDLE_BASE + 3;
private static final int BUNDLE_UNINSTALL = BUNDLE_BASE + 4;
private static final int BUNDLE_UPDATE = BUNDLE_BASE + 5;
private static final int BUNDLE_UPDATE_IS = BUNDLE_BASE + 6;
/**
* Constructs a new SecureAction object. The constructed SecureAction object
* uses the caller's AccessControlContext to perform security checks
*/
public SecurityUtil() {
// save the control context to be used.
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
controlContext = sm.getSecurityContext();
}
}
/**
* Creates a new Thread from a Runnable. Same as calling new
* Thread(target,name).
*
* @param target
* the Runnable to create the Thread from.
* @param name
* The name of the Thread.
* @return The new Thread
*/
public Thread createThread(final Runnable target, final String name) {
try {
return (Thread) PrivilegedRunner.doPrivileged(controlContext, this, CREATE_THREAD, target, name, null, null);
} catch (Exception t) {
throw new RuntimeException(t.getMessage());
}
}
/**
* 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 {
try {
return (Class<?>) PrivilegedRunner.doPrivileged(controlContext, this, CLASS_FOR_NAME, name, null, null, null);
} catch (ClassNotFoundException t) {
throw t;
} catch (Exception t) {
throw new RuntimeException(t.getMessage());
}
}
/**
* 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 (property == null) {
throw new NullPointerException("property is null");
}
String ret;
try {
ret = (String) PrivilegedRunner.doPrivileged(controlContext, this, SYSTEM_GET_PROPERTY, property, null, null, null);
} catch (Exception t) {
ret = null;
}
return ret;
}
/**
* Returns a system property. Same as calling
* System.getProperty(String,String).
*
* @param property
* the property key.
* @param def
* the default value if the property key does not exist.
* @return the value of the property or the default value if the property
* does not exist.
*/
public String getProperty(final String property, final String def) {
String ret = getProperty(property);
return ret != null ? ret : def;
}
/**
* Returns a boolean system property. Same as calling
* Boolean.getBoolean(String).
*
* @param property
* the property key.
* @return the value of the property or <code>false</code>, if not set
*/
public boolean getBooleanProperty(final String property) {
String ret = getProperty(property);
return ret != null ? Boolean.valueOf(ret).booleanValue() : false;
}
/**
* Sets a system property. Same as System.setProperty()
*
* @param key
* the name of the property
* @param value
* the value of the system property
* @return the old value of the property, or null
*/
public String setProperty(final String key, final String value) {
if (key == null) {
throw new NullPointerException("key is null");
}
if (value == null) {
throw new NullPointerException("key is null");
}
try {
return (String) PrivilegedRunner.doPrivileged(controlContext, this, SYSTEM_SET_PROPERTY, key, value, null, null);
} catch (Exception t) {
throw new RuntimeException(t.getMessage());
}
}
/**
* Creates a FileInputStream from a File. Same as calling new
* FileInputStream(File).
*
* @param file
* the File to create a FileInputStream from.
* @return The FileInputStream.
* @throws FileNotFoundException
* if the File does not exist.
*/
public FileInputStream getFileInputStream(final File file) throws FileNotFoundException {
try {
return (FileInputStream) PrivilegedRunner.doPrivileged(controlContext, this, FILE_GET_INPUT_STREAM, file, null, null, null);
} catch (FileNotFoundException t) {
throw t;
} catch (Exception t) {
throw new RuntimeException(t.getMessage());
}
}
/**
* Creates a random access file
*
* @param file
* the file object
* @param mode
* the open mode
* @return the random seekable file object
* @throws FileNotFoundException
* if the File does not exist
*/
public RandomAccessFile getRandomAccessFile(final File file, final String mode) throws FileNotFoundException {
try {
return (RandomAccessFile) PrivilegedRunner.doPrivileged(controlContext, this, FILE_GET_RANDOM_ACCESS_FILE, file, mode, null, null);
} catch (FileNotFoundException t) {
throw t;
} catch (Exception t) {
throw new RuntimeException(t.getMessage());
}
}
/**
* 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 {
try {
return (FileOutputStream) PrivilegedRunner.doPrivileged(//
controlContext, this, FILE_GET_OUTPUT_STREAM, file, //
append ? Boolean.TRUE : Boolean.FALSE, null, null);
} catch (FileNotFoundException t) {
throw t;
} catch (Exception t) {
throw new RuntimeException(t.getMessage());
}
}
/**
* 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) {
try {
return ((Boolean) PrivilegedRunner.doPrivileged(controlContext, this, FILE_EXISTS, file, null, null, null)).booleanValue();
} catch (Exception t) {
throw new RuntimeException(t.getMessage());
}
}
/**
* 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) {
try {
return ((Boolean) PrivilegedRunner.doPrivileged(controlContext, this, FILE_ISDIR, file, null, null, null)).booleanValue();
} catch (Exception t) {
throw new RuntimeException(t.getMessage());
}
}
/**
* Returns the length of a file. Same as calling file.length().
*
* @param file
* a file object
* @return the length of a file or -1 if file doesn't exists
*/
public long length(final File file) {
try {
return ((Long) PrivilegedRunner.doPrivileged(controlContext, this, FILE_LENGTH, file, null, null, null)).longValue();
} catch (Throwable t) {
return -1L;
}
}
/**
* Returns a file's last modified stamp. Same as calling
* file.lastModified().
*
* @param file
* a file object
* @return a file's last modified stamp or -1 if file doesn't exists
*/
public long lastModified(final File file) {
try {
return ((Long) PrivilegedRunner.doPrivileged(controlContext, this, FILE_LAST_MODIFIED, file, null, null, null)).longValue();
} catch (Exception t) {
return -1L;
}
}
/**
* 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) {
try {
return (String[]) PrivilegedRunner.doPrivileged(controlContext, this, FILE_LIST, file, null, null, null);
} catch (Exception t) {
return null;
}
}
/**
* Deletes the specified file. Same as File.delete()
*
* @param file
* the file object
* @return if delete succeeded
*/
public boolean delete(final File file) {
try {
return ((Boolean) PrivilegedRunner.doPrivileged(controlContext, this, FILE_DELETE, file, null, null, null)).booleanValue();
} catch (Exception t) {
throw new RuntimeException(t.getMessage());
}
}
/**
* Renames the source file to the target name. Same as File.renameTo(File)
*
* @param source
* the file object, that will be renamed
* @param target
* the target file name
* @return if rename succeeded
*/
public boolean renameTo(final File source, final File target) {
try {
return ((Boolean) PrivilegedRunner.doPrivileged(controlContext, this, FILE_RENAME, source, target, null, null)).booleanValue();
} catch (Exception t) {
throw new RuntimeException(t.getMessage());
}
}
/**
* Gets a service object. Same as calling context.getService(reference)
*
* @param reference
* the ServiceReference
* @param context
* the BundleContext
* @return a service object
*/
public Object getService(final ServiceReference<?> reference, final BundleContext context) {
if (context == null) {
throw new NullPointerException("Context is null");
}
if (reference == null) {
throw new NullPointerException("Reference is null");
}
try {
return PrivilegedRunner.doPrivileged(controlContext, this, SERVICE_GET_SERVICE, context, reference, null, null);
} catch (Exception t) {
throw new RuntimeException(t.getMessage());
}
}
/**
* Gets a reference for the specified service(s). Same as calling
* context.getServiceReferences(class, filter)
*
* @param clazz
* the name of the requested service class
* @param filter
* an LDAP filter
* @param context
* the BundleContext
* @return a list of reference or <code>null</code>
* @throws InvalidSyntaxException
* if filter is not correct
*/
public ServiceReference<?>[] getServiceReferences(String clazz, String filter, BundleContext context) throws InvalidSyntaxException {
if (context == null) {
throw new NullPointerException("Context is null");
}
if (clazz == null && filter == null) {
throw new NullPointerException("Either filter or clazz parameter should not be null");
}
try {
return (ServiceReference[]) PrivilegedRunner.doPrivileged(controlContext, this, SERVICE_GET_REFERENCE, context, clazz, filter, null);
} catch (InvalidSyntaxException e) {
throw e;
} catch (Exception t) {
throw new RuntimeException(t.getMessage());
}
}
/**
* Registers a service. Same as BundleContext.register(clazz, service,
* properties);
*
* @param clazz
* the class name of the service
* @param service
* the service instance
* @param properties
* the properties.
* @param context
* the bundle context
* @return a service registration
*/
public ServiceRegistration<?> registerService(String clazz, Object service, Dictionary<?, ?> properties, BundleContext context) {
if (context == null) {
throw new NullPointerException("Context is null");
}
if (service == null) {
throw new NullPointerException("Service is null");
}
if (clazz == null) {
throw new NullPointerException("Class name is null");
}
try {
return (ServiceRegistration<?>) PrivilegedRunner.doPrivileged(controlContext, this, SERVICE_REG_CLASS, context, clazz, service, properties);
} catch (Exception t) {
throw new RuntimeException(t.getMessage());
}
}
/**
* Registers a instance that implements many services. Same as
* BundleContext.register(clases, service, properties);
*
* @param classes
* the class names of the service
* @param service
* the service instance
* @param properties
* the properties.
* @param context
* the bundle context
* @return a service registration
*/
public ServiceRegistration<?> registerService(String[] classes, Object service, Dictionary<?, ?> properties, BundleContext context) {
if (context == null) {
throw new NullPointerException("Context is null");
}
if (service == null) {
throw new NullPointerException("Service is null");
}
if (classes == null) {
throw new NullPointerException("Class names are null");
}
try {
return (ServiceRegistration<?>) PrivilegedRunner.doPrivileged(controlContext, this, SERVICE_REG_CLASSES, context, classes, service, properties);
} catch (Exception t) {
throw new RuntimeException(t.getMessage());
}
}
/**
* Gets the location of the bundle. Same as Bundle.getLocation().
*
* @param bundle
* the bundle
* @return the bundle location
*/
public String getLocation(Bundle bundle) {
try {
return (String) PrivilegedRunner.doPrivileged(controlContext, this, BUNDLE_GET_LOCATION, bundle, null, null, null);
} catch (Exception t) {
throw new RuntimeException(t.getMessage());
}
}
/**
* Gets the bundle headers. Same as Bundle.getHeaders().
*
* @param bundle
* the bundle
* @return the bundle location
*/
public Dictionary<?, ?> getHeaders(Bundle bundle) {
try {
return (Dictionary<?, ?>) PrivilegedRunner.doPrivileged(controlContext, this, BUNDLE_GET_HEADERS, bundle, null, null, null);
} catch (Exception t) {
throw new RuntimeException(t.getMessage());
}
}
/**
* Starts the bundle. Same as Bundle.start()
*
* @param bundle
* the bundle
* @throws BundleException
*/
public void start(Bundle bundle) throws BundleException {
try {
PrivilegedRunner.doPrivileged(controlContext, this, BUNDLE_START, bundle, null, null, null);
} catch (BundleException t) {
throw t;
} catch (Exception t) {
throw new RuntimeException(t.getMessage());
}
}
/**
* Stops the bundle. Same as Bundle.stop()
*
* @param bundle
* the bundle
* @throws BundleException
*/
public void stop(Bundle bundle) throws BundleException {
try {
PrivilegedRunner.doPrivileged(controlContext, this, BUNDLE_STOP, bundle, null, null, null);
} catch (BundleException t) {
throw t;
} catch (Exception t) {
throw new RuntimeException(t.getMessage());
}
}
/**
* Un-installs the bundle. Same as Bundle.uninstall()
*
* @param bundle
* the bundle
* @throws BundleException
*/
public void uninstall(Bundle bundle) throws BundleException {
try {
PrivilegedRunner.doPrivileged(controlContext, this, BUNDLE_UNINSTALL, bundle, null, null, null);
} catch (BundleException t) {
throw t;
} catch (Exception t) {
throw new RuntimeException(t.getMessage());
}
}
/**
* Updates the bundle. Same as Bundle.update()
*
* @param bundle
* the bundle
* @throws BundleException
*/
public void update(Bundle bundle) throws BundleException {
try {
PrivilegedRunner.doPrivileged(controlContext, this, BUNDLE_UPDATE, bundle, null, null, null);
} catch (BundleException t) {
throw t;
} catch (Exception t) {
throw new RuntimeException(t.getMessage());
}
}
/**
* Updates the bundle from stream. Same as Bundle.update(stream)
*
* @param bundle
* the bundle
* @param is
* the stream
* @throws BundleException
*/
public void update(Bundle bundle, InputStream is) throws BundleException {
try {
PrivilegedRunner.doPrivileged(controlContext, this, BUNDLE_UPDATE_IS, bundle, is, null, null);
} catch (BundleException t) {
throw t;
} catch (Exception t) {
throw new RuntimeException(t.getMessage());
}
}
/**
* Performs a privileged action <b>using the current security context</b>.
* The method calls the dispatcher inside the privileged call passing it the
* same parameters that were passed to this method.
*
* @param dispatcher
* the dispatcher which should be called
* @param type
* the type of the action - used in the dispatcher
* @param arg1
* a parameter received by the dispatcher
* @param arg2
* a parameter received by the dispatcher
* @param arg3
* a parameter received by the dispatcher
* @param arg4
* a parameter received by the dispatcher
* @return the object returned from the execution
* @throws Exception
* if the dispatcher fails
* @see PrivilegedRunner#doPrivileged(Object,
* org.eclipse.equinox.internal.util.security.PrivilegedRunner.PrivilegedDispatcher,
* int, Object, Object, Object, Object)
*/
public Object doPrivileged(PrivilegedRunner.PrivilegedDispatcher dispatcher, int type, Object arg1, Object arg2, Object arg3, Object arg4) throws Exception {
return PrivilegedRunner.doPrivileged(controlContext, dispatcher, type, arg1, arg2, arg3, arg4);
}
/**
* Performs a privileged action <b>using the current security context</b>.
* The method calls the dispatcher inside the privileged call passing it the
* same parameters that were passed to this method.
*
* @param dispatcher
* the dispatcher which should be called
* @param type
* the type of the action - used in the dispatcher
* @param arg1
* a parameter received by the dispatcher
* @param arg2
* a parameter received by the dispatcher
* @param arg3
* a parameter received by the dispatcher
* @return the object returned from the execution
* @throws Exception
* if the dispatcher fails
* @see PrivilegedRunner#doPrivileged(Object,
* org.eclipse.equinox.internal.util.security.PrivilegedRunner.PrivilegedDispatcher,
* int, Object, Object, Object, Object)
*/
public Object doPrivileged(PrivilegedRunner.PrivilegedDispatcher dispatcher, int type, Object arg1, Object arg2, Object arg3) throws Exception {
return PrivilegedRunner.doPrivileged(controlContext, dispatcher, type, arg1, arg2, arg3, null);
}
/**
* Performs a privileged action <b>using the current security context</b>.
* The method calls the dispatcher inside the privileged call passing it the
* same parameters that were passed to this method.
*
* @param dispatcher
* the dispatcher which should be called
* @param type
* the type of the action - used in the dispatcher
* @param arg1
* a parameter received by the dispatcher
* @param arg2
* a parameter received by the dispatcher
* @return the object returned from the execution
* @throws Exception
* if the dispatcher fails
* @see PrivilegedRunner#doPrivileged(Object,
* org.eclipse.equinox.internal.util.security.PrivilegedRunner.PrivilegedDispatcher,
* int, Object, Object, Object, Object)
*/
public Object doPrivileged(PrivilegedRunner.PrivilegedDispatcher dispatcher, int type, Object arg1, Object arg2) throws Exception {
return PrivilegedRunner.doPrivileged(controlContext, dispatcher, type, arg1, arg2, null, null);
}
/**
* Performs a privileged action <b>using the current security context</b>.
* The method calls the dispatcher inside the privileged call passing it the
* same parameters that were passed to this method.
*
* @param dispatcher
* the dispatcher which should be called
* @param type
* the type of the action - used in the dispatcher
* @param arg1
* a parameter received by the dispatcher
* @return the object returned from the execution
* @throws Exception
* if the dispatcher fails
* @see PrivilegedRunner#doPrivileged(Object,
* org.eclipse.equinox.internal.util.security.PrivilegedRunner.PrivilegedDispatcher,
* int, Object, Object, Object, Object)
*/
public Object doPrivileged(PrivilegedRunner.PrivilegedDispatcher dispatcher, int type, Object arg1) throws Exception {
return PrivilegedRunner.doPrivileged(controlContext, dispatcher, type, arg1, null, null, null);
}
@SuppressWarnings("unchecked")
@Override
public Object dispatchPrivileged(int type, Object arg1, Object arg2, Object arg3, Object arg4) throws Exception {
switch (type) {
case SYSTEM_GET_PROPERTY :
return UtilActivator.bc.getProperty((String) arg1);
case CREATE_THREAD :
return new Thread((Runnable) arg1, (String) arg2);
case CLASS_FOR_NAME :
return Class.forName((String) arg1);
case SYSTEM_SET_PROPERTY :
return System.getProperties().put(arg1, arg2);
case FILE_GET_INPUT_STREAM :
return new FileInputStream((File) arg1);
case FILE_GET_OUTPUT_STREAM :
return new FileOutputStream(((File) arg1).getAbsolutePath(), ((Boolean) arg2).booleanValue());
case FILE_LENGTH :
return new Long(((File) arg1).length());
case FILE_EXISTS :
return ((File) arg1).exists() ? Boolean.TRUE : Boolean.FALSE;
case FILE_ISDIR :
return ((File) arg1).isDirectory() ? Boolean.TRUE : Boolean.FALSE;
case FILE_LAST_MODIFIED :
return new Long(((File) arg1).lastModified());
case FILE_LIST :
return ((File) arg1).list();
case FILE_DELETE :
return ((File) arg1).delete() ? Boolean.TRUE : Boolean.FALSE;
case FILE_RENAME :
return ((File) arg1).renameTo(((File) arg2)) ? Boolean.TRUE : Boolean.FALSE;
case FILE_GET_RANDOM_ACCESS_FILE :
return new RandomAccessFile((File) arg1, (String) arg2);
case SERVICE_GET_REFERENCE :
return ((BundleContext) arg1).getServiceReferences((String) arg2, (String) arg3);
case SERVICE_GET_SERVICE :
return ((BundleContext) arg1).getService((ServiceReference<?>) arg2);
case SERVICE_REG_CLASS :
return ((BundleContext) arg1).registerService((String) arg2, arg3, (Dictionary<String, ?>) arg4);
case SERVICE_REG_CLASSES :
return ((BundleContext) arg1).registerService((String[]) arg2, arg3, (Dictionary<String, ?>) arg4);
case BUNDLE_GET_LOCATION :
return ((Bundle) arg1).getLocation();
case BUNDLE_GET_HEADERS :
return ((Bundle) arg1).getHeaders();
case BUNDLE_START :
((Bundle) arg1).start();
break;
case BUNDLE_STOP :
((Bundle) arg1).stop();
break;
case BUNDLE_UNINSTALL :
((Bundle) arg1).uninstall();
break;
case BUNDLE_UPDATE :
((Bundle) arg1).update();
break;
case BUNDLE_UPDATE_IS :
((Bundle) arg1).update((InputStream) arg2);
break;
}
return null;
}
}