Return-Path: X-Original-To: apmail-incubator-ace-commits-archive@minotaur.apache.org Delivered-To: apmail-incubator-ace-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 14EA288AD for ; Tue, 13 Sep 2011 14:07:00 +0000 (UTC) Received: (qmail 92883 invoked by uid 500); 13 Sep 2011 14:07:00 -0000 Delivered-To: apmail-incubator-ace-commits-archive@incubator.apache.org Received: (qmail 92858 invoked by uid 500); 13 Sep 2011 14:07:00 -0000 Mailing-List: contact ace-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: ace-dev@incubator.apache.org Delivered-To: mailing list ace-commits@incubator.apache.org Received: (qmail 92850 invoked by uid 99); 13 Sep 2011 14:06:59 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 13 Sep 2011 14:06:59 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED,T_FRT_ADULT2 X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 13 Sep 2011 14:06:47 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id A9A462388A5F; Tue, 13 Sep 2011 14:06:24 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1170188 [5/7] - in /incubator/ace/trunk: ./ ace-deployment-verifier-ui/ ace-deployment-verifier-ui/src/ ace-deployment-verifier-ui/src/main/ ace-deployment-verifier-ui/src/main/java/ ace-deployment-verifier-ui/src/main/java/org/ ace-deploy... Date: Tue, 13 Sep 2011 14:06:22 -0000 To: ace-commits@incubator.apache.org From: pauls@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20110913140624.A9A462388A5F@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Added: incubator/ace/trunk/ace-deployment-verifier/src/main/java/org/apache/felix/framework/util/SecureAction.java URL: http://svn.apache.org/viewvc/incubator/ace/trunk/ace-deployment-verifier/src/main/java/org/apache/felix/framework/util/SecureAction.java?rev=1170188&view=auto ============================================================================== --- incubator/ace/trunk/ace-deployment-verifier/src/main/java/org/apache/felix/framework/util/SecureAction.java (added) +++ incubator/ace/trunk/ace-deployment-verifier/src/main/java/org/apache/felix/framework/util/SecureAction.java Tue Sep 13 14:06:20 2011 @@ -0,0 +1,1676 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 + * + * http://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 org.apache.felix.framework.util; + +import java.io.*; +import java.lang.reflect.*; +import java.net.*; +import java.security.*; +import java.util.Collection; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Map; +import java.util.zip.ZipFile; +import org.osgi.framework.Bundle; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleEvent; +import org.osgi.framework.ServiceEvent; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.hooks.resolver.ResolverHook; +import org.osgi.framework.hooks.service.ListenerHook; +import org.osgi.framework.wiring.BundleCapability; +import org.osgi.framework.wiring.BundleRequirement; +import org.osgi.framework.wiring.BundleRevision; + +/** + *

+ * This is a utility class to centralize all action that should be performed + * in a doPrivileged() block. To perform a secure action, simply + * create an instance of this class and use the specific method to perform + * the desired action. When an instance is created, this class will capture + * the security context and will then use that context when checking for + * permission to perform the action. Instances of this class should not be + * passed around since they may grant the receiver a capability to perform + * privileged actions. + *

+**/ +public class SecureAction +{ + private static final ThreadLocal m_actions = new ThreadLocal() + { + public Object initialValue() + { + return new Actions(); + } + }; + + protected static transient int BUFSIZE = 4096; + + private AccessControlContext m_acc = null; + + public SecureAction() + { + if (System.getSecurityManager() != null) + { + try + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.INITIALIZE_CONTEXT_ACTION, null); + m_acc = (AccessControlContext) AccessController.doPrivileged(actions); + } + catch (PrivilegedActionException ex) + { + throw (RuntimeException) ex.getException(); + } + } + else + { + m_acc = AccessController.getContext(); + } + } + + public String getSystemProperty(String name, String def) + { + if (System.getSecurityManager() != null) + { + try + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.GET_PROPERTY_ACTION, name, def); + return (String) AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException ex) + { + throw (RuntimeException) ex.getException(); + } + } + else + { + return System.getProperty(name, def); + } + } + + public ClassLoader getParentClassLoader(ClassLoader loader) + { + if (System.getSecurityManager() != null) + { + try + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.GET_PARENT_CLASS_LOADER_ACTION, loader); + return (ClassLoader) AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException ex) + { + throw (RuntimeException) ex.getException(); + } + } + else + { + return loader.getParent(); + } + } + + public ClassLoader getSystemClassLoader() + { + if (System.getSecurityManager() != null) + { + try + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.GET_SYSTEM_CLASS_LOADER_ACTION); + return (ClassLoader) AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException ex) + { + throw (RuntimeException) ex.getException(); + } + } + else + { + return ClassLoader.getSystemClassLoader(); + } + } + + public ClassLoader getClassLoader(Class clazz) + { + if (System.getSecurityManager() != null) + { + try + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.GET_CLASS_LOADER_ACTION, clazz); + return (ClassLoader) AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException ex) + { + throw (RuntimeException) ex.getException(); + } + } + else + { + return clazz.getClassLoader(); + } + } + + public Class forName(String name) throws ClassNotFoundException + { + if (System.getSecurityManager() != null) + { + try + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.FOR_NAME_ACTION, name); + return (Class) AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException ex) + { + if (ex.getException() instanceof ClassNotFoundException) + { + throw (ClassNotFoundException) ex.getException(); + } + throw (RuntimeException) ex.getException(); + } + } + else + { + return Class.forName(name); + } + } + + public URL createURL(String protocol, String host, + int port, String path, URLStreamHandler handler) + throws MalformedURLException + { + if (System.getSecurityManager() != null) + { + try + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.CREATE_URL_ACTION, protocol, host, + new Integer(port), path, handler); + return (URL) AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException ex) + { + if (ex.getException() instanceof MalformedURLException) + { + throw (MalformedURLException) ex.getException(); + } + throw (RuntimeException) ex.getException(); + } + } + else + { + return new URL(protocol, host, port, path, handler); + } + } + + public URL createURL(URL context, String spec, URLStreamHandler handler) + throws MalformedURLException + { + if (System.getSecurityManager() != null) + { + try + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.CREATE_URL_WITH_CONTEXT_ACTION, context, + spec, handler); + return (URL) AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException ex) + { + if (ex.getException() instanceof MalformedURLException) + { + throw (MalformedURLException) ex.getException(); + } + throw (RuntimeException) ex.getException(); + } + } + else + { + return new URL(context, spec, handler); + } + } + + public Process exec(String command) throws IOException + { + if (System.getSecurityManager() != null) + { + try + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.EXEC_ACTION, command); + return (Process) AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException ex) + { + throw (RuntimeException) ex.getException(); + } + } + else + { + return Runtime.getRuntime().exec(command); + } + } + + public String getAbsolutePath(File file) + { + if (System.getSecurityManager() != null) + { + try + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.GET_ABSOLUTE_PATH_ACTION, file); + return (String) AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException ex) + { + throw (RuntimeException) ex.getException(); + } + } + else + { + return file.getAbsolutePath(); + } + } + + public boolean fileExists(File file) + { + if (System.getSecurityManager() != null) + { + try + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.FILE_EXISTS_ACTION, file); + return ((Boolean) AccessController.doPrivileged(actions, m_acc)) + .booleanValue(); + } + catch (PrivilegedActionException ex) + { + throw (RuntimeException) ex.getException(); + } + } + else + { + return file.exists(); + } + } + + public boolean isFileDirectory(File file) + { + if (System.getSecurityManager() != null) + { + try + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.FILE_IS_DIRECTORY_ACTION, file); + return ((Boolean) AccessController.doPrivileged(actions, m_acc)) + .booleanValue(); + } + catch (PrivilegedActionException ex) + { + throw (RuntimeException) ex.getException(); + } + } + else + { + return file.isDirectory(); + } + } + + public boolean mkdir(File file) + { + if (System.getSecurityManager() != null) + { + try + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.MAKE_DIRECTORY_ACTION, file); + return ((Boolean) AccessController.doPrivileged(actions, m_acc)) + .booleanValue(); + } + catch (PrivilegedActionException ex) + { + throw (RuntimeException) ex.getException(); + } + } + else + { + return file.mkdir(); + } + } + + public boolean mkdirs(File file) + { + if (System.getSecurityManager() != null) + { + try + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.MAKE_DIRECTORIES_ACTION, file); + return ((Boolean) AccessController.doPrivileged(actions, m_acc)) + .booleanValue(); + } + catch (PrivilegedActionException ex) + { + throw (RuntimeException) ex.getException(); + } + } + else + { + return file.mkdirs(); + } + } + + public File[] listDirectory(File file) + { + if (System.getSecurityManager() != null) + { + try + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.LIST_DIRECTORY_ACTION, file); + return (File[]) AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException ex) + { + throw (RuntimeException) ex.getException(); + } + } + else + { + return file.listFiles(); + } + } + + public boolean renameFile(File oldFile, File newFile) + { + if (System.getSecurityManager() != null) + { + try + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.RENAME_FILE_ACTION, oldFile, newFile); + return ((Boolean) AccessController.doPrivileged(actions, m_acc)) + .booleanValue(); + } + catch (PrivilegedActionException ex) + { + throw (RuntimeException) ex.getException(); + } + } + else + { + return oldFile.renameTo(newFile); + } + } + + public FileInputStream getFileInputStream(File file) throws IOException + { + if (System.getSecurityManager() != null) + { + try + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.GET_FILE_INPUT_ACTION, file); + return (FileInputStream) AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException ex) + { + if (ex.getException() instanceof IOException) + { + throw (IOException) ex.getException(); + } + throw (RuntimeException) ex.getException(); + } + } + else + { + return new FileInputStream(file); + } + } + + public FileOutputStream getFileOutputStream(File file) throws IOException + { + if (System.getSecurityManager() != null) + { + try + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.GET_FILE_OUTPUT_ACTION, file); + return (FileOutputStream) AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException ex) + { + if (ex.getException() instanceof IOException) + { + throw (IOException) ex.getException(); + } + throw (RuntimeException) ex.getException(); + } + } + else + { + return new FileOutputStream(file); + } + } + + public URI toURI(File file) + { + if (System.getSecurityManager() != null) + { + try + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.TO_URI_ACTION, file); + return (URI) AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException ex) + { + throw (RuntimeException) ex.getException(); + } + } + else + { + return file.toURI(); + } + } + + public InputStream getURLConnectionInputStream(URLConnection conn) + throws IOException + { + if (System.getSecurityManager() != null) + { + try + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.GET_URL_INPUT_ACTION, conn); + return (InputStream) AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException ex) + { + if (ex.getException() instanceof IOException) + { + throw (IOException) ex.getException(); + } + throw (RuntimeException) ex.getException(); + } + } + else + { + return conn.getInputStream(); + } + } + + public boolean deleteFile(File target) + { + if (System.getSecurityManager() != null) + { + try + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.DELETE_FILE_ACTION, target); + return ((Boolean) AccessController.doPrivileged(actions, m_acc)) + .booleanValue(); + } + catch (PrivilegedActionException ex) + { + throw (RuntimeException) ex.getException(); + } + } + else + { + return target.delete(); + } + } + + public File createTempFile(String prefix, String suffix, File dir) + throws IOException + { + if (System.getSecurityManager() != null) + { + try + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.CREATE_TMPFILE_ACTION, prefix, suffix, dir); + return (File) AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException ex) + { + if (ex.getException() instanceof IOException) + { + throw (IOException) ex.getException(); + } + throw (RuntimeException) ex.getException(); + } + } + else + { + return File.createTempFile(prefix, suffix, dir); + } + } + + public URLConnection openURLConnection(URL url) throws IOException + { + if (System.getSecurityManager() != null) + { + try + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.OPEN_URLCONNECTION_ACTION, url); + return (URLConnection) AccessController.doPrivileged(actions, + m_acc); + } + catch (PrivilegedActionException ex) + { + if (ex.getException() instanceof IOException) + { + throw (IOException) ex.getException(); + } + throw (RuntimeException) ex.getException(); + } + } + else + { + return url.openConnection(); + } + } + + public ZipFile openZipFile(File file) throws IOException + { + if (System.getSecurityManager() != null) + { + try + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.OPEN_ZIPFILE_ACTION, file); + return (ZipFile) AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException ex) + { + if (ex.getException() instanceof IOException) + { + throw (IOException) ex.getException(); + } + throw (RuntimeException) ex.getException(); + } + } + else + { + return new ZipFile(file); + } + } + + public void startActivator(BundleActivator activator, BundleContext context) + throws Exception + { + if (System.getSecurityManager() != null) + { + try + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.START_ACTIVATOR_ACTION, activator, context); + AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException ex) + { + throw ex.getException(); + } + } + else + { + activator.start(context); + } + } + + public void stopActivator(BundleActivator activator, BundleContext context) + throws Exception + { + if (System.getSecurityManager() != null) + { + try + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.STOP_ACTIVATOR_ACTION, activator, context); + AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException ex) + { + throw ex.getException(); + } + } + else + { + activator.stop(context); + } + } + + public Policy getPolicy() + { + if (System.getSecurityManager() != null) + { + try + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.GET_POLICY_ACTION, null); + return (Policy) AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException ex) + { + throw (RuntimeException) ex.getException(); + } + } + else + { + return Policy.getPolicy(); + } + } + + public void addURLToURLClassLoader(URL extension, ClassLoader loader) throws Exception + { + if (System.getSecurityManager() != null) + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.ADD_EXTENSION_URL_ACTION, extension, loader); + try + { + AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException e) + { + throw e.getException(); + } + } + else + { + Method addURL = + URLClassLoader.class.getDeclaredMethod("addURL", + new Class[] {URL.class}); + addURL.setAccessible(true); + addURL.invoke(loader, new Object[]{extension}); + } + } + + public Constructor getConstructor(Class target, Class[] types) throws Exception + { + if (System.getSecurityManager() != null) + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.GET_CONSTRUCTOR_ACTION, target, types); + try + { + return (Constructor) AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException e) + { + throw e.getException(); + } + } + else + { + return target.getConstructor(types); + } + } + + public Constructor getDeclaredConstructor(Class target, Class[] types) throws Exception + { + if (System.getSecurityManager() != null) + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.GET_DECLARED_CONSTRUCTOR_ACTION, target, types); + try + { + return (Constructor) AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException e) + { + throw e.getException(); + } + } + else + { + return target.getDeclaredConstructor(types); + } + } + + public Method getMethod(Class target, String method, Class[] types) throws Exception + { + if (System.getSecurityManager() != null) + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.GET_METHOD_ACTION, target, method, types); + try + { + return (Method) AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException e) + { + throw e.getException(); + } + } + else + { + return target.getMethod(method, types); + } + } + + public Method getDeclaredMethod(Class target, String method, Class[] types) throws Exception + { + if (System.getSecurityManager() != null) + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.GET_DECLARED_METHOD_ACTION, target, method, types); + try + { + return (Method) AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException e) + { + throw e.getException(); + } + } + else + { + return target.getDeclaredMethod(method, types); + } + } + + public void setAccesssible(AccessibleObject ao) + { + if (System.getSecurityManager() != null) + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.SET_ACCESSIBLE_ACTION, ao); + try + { + AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException e) + { + throw (RuntimeException) e.getException(); + } + } + else + { + ao.setAccessible(true); + } + } + + public Object invoke(Method method, Object target, Object[] params) throws Exception + { + if (System.getSecurityManager() != null) + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.INVOKE_METHOD_ACTION, method, target, params); + try + { + return AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException e) + { + throw e.getException(); + } + } + else + { + method.setAccessible(true); + return method.invoke(target, params); + } + } + + public Object invokeDirect(Method method, Object target, Object[] params) throws Exception + { + if (System.getSecurityManager() != null) + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.INVOKE_DIRECTMETHOD_ACTION, method, target, params); + try + { + return AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException e) + { + throw e.getException(); + } + } + else + { + return method.invoke(target, params); + } + } + + public Object invoke(Constructor constructor, Object[] params) throws Exception + { + if (System.getSecurityManager() != null) + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.INVOKE_CONSTRUCTOR_ACTION, constructor, params); + try + { + return AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException e) + { + throw e.getException(); + } + } + else + { + return constructor.newInstance(params); + } + } + + public Object getDeclaredField(Class targetClass, String name, Object target) + throws Exception + { + if (System.getSecurityManager() != null) + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.GET_FIELD_ACTION, targetClass, name, target); + try + { + return AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException e) + { + throw e.getException(); + } + } + else + { + Field field = targetClass.getDeclaredField(name); + field.setAccessible(true); + + return field.get(target); + } + } + + public Object swapStaticFieldIfNotClass(Class targetClazz, + Class targetType, Class condition, String lockName) throws Exception + { + if (System.getSecurityManager() != null) + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.SWAP_FIELD_ACTION, targetClazz, targetType, + condition, lockName); + try + { + return AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException e) + { + throw e.getException(); + } + } + else + { + return _swapStaticFieldIfNotClass(targetClazz, targetType, + condition, lockName); + } + } + + private static Object _swapStaticFieldIfNotClass(Class targetClazz, + Class targetType, Class condition, String lockName) throws Exception + { + Object lock = null; + if (lockName != null) + { + try + { + Field lockField = + targetClazz.getDeclaredField(lockName); + lockField.setAccessible(true); + lock = lockField.get(null); + } + catch (NoSuchFieldException ex) + { + } + } + if (lock == null) + { + lock = targetClazz; + } + synchronized (lock) + { + Field[] fields = targetClazz.getDeclaredFields(); + + Object result = null; + for (int i = 0; (i < fields.length) && (result == null); i++) + { + if (Modifier.isStatic(fields[i].getModifiers()) && + (fields[i].getType() == targetType)) + { + fields[i].setAccessible(true); + + result = fields[i].get(null); + + if (result != null) + { + if ((condition == null) || + !result.getClass().getName().equals(condition.getName())) + { + fields[i].set(null, null); + } + } + } + } + if (result != null) + { + if ((condition == null) || !result.getClass().getName().equals(condition.getName())) + { + // reset cache + for (int i = 0; i < fields.length; i++) + { + if (Modifier.isStatic(fields[i].getModifiers()) && + (fields[i].getType() == Hashtable.class)) + { + fields[i].setAccessible(true); + Hashtable cache = (Hashtable) fields[i].get(null); + if (cache != null) + { + cache.clear(); + } + } + } + } + return result; + } + } + return null; + } + + public void flush(Class targetClazz, Object lock) throws Exception + { + if (System.getSecurityManager() != null) + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.FLUSH_FIELD_ACTION, targetClazz, lock); + try + { + AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException e) + { + throw e.getException(); + } + } + else + { + _flush(targetClazz, lock); + } + } + + private static void _flush(Class targetClazz, Object lock) throws Exception + { + synchronized (lock) + { + Field[] fields = targetClazz.getDeclaredFields(); + // reset cache + for (int i = 0; i < fields.length; i++) + { + if (Modifier.isStatic(fields[i].getModifiers()) && + ((fields[i].getType() == Hashtable.class) || (fields[i].getType() == HashMap.class))) + { + fields[i].setAccessible(true); + if (fields[i].getType() == Hashtable.class) + { + Hashtable cache = (Hashtable) fields[i].get(null); + if (cache != null) + { + cache.clear(); + } + } + else + { + HashMap cache = (HashMap) fields[i].get(null); + if (cache != null) + { + cache.clear(); + } + } + } + } + } + } + + /* public void invokeBundleFindHook( + org.osgi.framework.hooks.bundle.FindHook fh, + BundleContext bc, Collection bundles) + throws Exception + { + if (System.getSecurityManager() != null) + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.INVOKE_BUNDLE_FIND_HOOK, fh, bc, bundles); + try + { + AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException e) + { + throw e.getException(); + } + } + else + { + fh.find(bc, bundles); + } + } + + public void invokeBundleEventHook( + org.osgi.framework.hooks.bundle.EventHook eh, + BundleEvent event, Collection contexts) + throws Exception + { + if (System.getSecurityManager() != null) + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.INVOKE_BUNDLE_EVENT_HOOK, eh, contexts); + try + { + AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException e) + { + throw e.getException(); + } + } + else + { + eh.event(event, contexts); + } + } + + public void invokeWeavingHook( + org.osgi.framework.hooks.weaving.WeavingHook wh, + org.osgi.framework.hooks.weaving.WovenClass wc) + throws Exception + { + if (System.getSecurityManager() != null) + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.INVOKE_WEAVING_HOOK, wh, wc); + try + { + AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException e) + { + throw e.getException(); + } + } + else + { + wh.weave(wc); + } + } + + public void invokeServiceEventHook( + org.osgi.framework.hooks.service.EventHook eh, + ServiceEvent event, Collection contexts) + throws Exception + { + if (System.getSecurityManager() != null) + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.INVOKE_SERVICE_EVENT_HOOK, eh, contexts); + try + { + AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException e) + { + throw e.getException(); + } + } + else + { + eh.event(event, contexts); + } + } + + public void invokeServiceFindHook( + org.osgi.framework.hooks.service.FindHook fh, + BundleContext context, String name, String filter, + boolean allServices, Collection> references) + throws Exception + { + if (System.getSecurityManager() != null) + { + Actions actions = (Actions) m_actions.get(); + actions.set( + Actions.INVOKE_SERVICE_EVENT_HOOK, fh, context, name, filter, + (allServices) ? Boolean.TRUE : Boolean.FALSE, references); + try + { + AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException e) + { + throw e.getException(); + } + } + else + { + fh.find(context, name, filter, allServices, references); + } + } + + public void invokeServiceListenerHookAdded( + org.osgi.framework.hooks.service.ListenerHook lh, + Collection listeners) + throws Exception + { + if (System.getSecurityManager() != null) + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.INVOKE_SERVICE_LISTENER_HOOK_ADDED, lh, listeners); + try + { + AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException e) + { + throw e.getException(); + } + } + else + { + lh.added(listeners); + } + } + + public void invokeServiceListenerHookRemoved( + org.osgi.framework.hooks.service.ListenerHook lh, + Collection listeners) + throws Exception + { + if (System.getSecurityManager() != null) + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.INVOKE_SERVICE_LISTENER_HOOK_REMOVED, lh, listeners); + try + { + AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException e) + { + throw e.getException(); + } + } + else + { + lh.removed(listeners); + } + } + + public void invokeServiceEventListenerHook( + org.osgi.framework.hooks.service.EventListenerHook elh, + ServiceEvent event, + Map> listeners) + throws Exception + { + if (System.getSecurityManager() != null) + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.INVOKE_SERVICE_EVENT_LISTENER_HOOK, elh, listeners); + try + { + AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException e) + { + throw e.getException(); + } + } + else + { + elh.event(event, listeners); + } + } + + public ResolverHook invokeResolverHookFactory( + org.osgi.framework.hooks.resolver.ResolverHookFactory rhf, + Collection triggers) + throws Exception + { + if (System.getSecurityManager() != null) + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.INVOKE_RESOLVER_HOOK_FACTORY, rhf, triggers); + try + { + return (ResolverHook) AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException e) + { + throw e.getException(); + } + } + else + { + return rhf.begin(triggers); + } + } + + public void invokeResolverHookResolvable( + org.osgi.framework.hooks.resolver.ResolverHook rh, + Collection candidates) + throws Exception + { + if (System.getSecurityManager() != null) + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.INVOKE_RESOLVER_HOOK_RESOLVABLE, rh, candidates); + try + { + AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException e) + { + throw e.getException(); + } + } + else + { + rh.filterResolvable(candidates); + } + } + + public void invokeResolverHookSingleton( + org.osgi.framework.hooks.resolver.ResolverHook rh, + BundleCapability singleton, + Collection collisions) + throws Exception + { + if (System.getSecurityManager() != null) + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.INVOKE_RESOLVER_HOOK_SINGLETON, rh, singleton, collisions); + try + { + AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException e) + { + throw e.getException(); + } + } + else + { + rh.filterSingletonCollisions(singleton, collisions); + } + } + + public void invokeResolverHookMatches( + org.osgi.framework.hooks.resolver.ResolverHook rh, + BundleRequirement req, + Collection candidates) + throws Exception + { + if (System.getSecurityManager() != null) + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.INVOKE_RESOLVER_HOOK_MATCHES, rh, req, candidates); + try + { + AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException e) + { + throw e.getException(); + } + } + else + { + rh.filterMatches(req, candidates); + } + } + + public void invokeResolverHookEnd( + org.osgi.framework.hooks.resolver.ResolverHook rh) + throws Exception + { + if (System.getSecurityManager() != null) + { + Actions actions = (Actions) m_actions.get(); + actions.set(Actions.INVOKE_RESOLVER_HOOK_END, rh); + try + { + AccessController.doPrivileged(actions, m_acc); + } + catch (PrivilegedActionException e) + { + throw e.getException(); + } + } + else + { + rh.end(); + } + } +*/ + private static class Actions implements PrivilegedExceptionAction + { + public static final int INITIALIZE_CONTEXT_ACTION = 0; + public static final int ADD_EXTENSION_URL_ACTION = 1; + public static final int CREATE_TMPFILE_ACTION = 2; + public static final int CREATE_URL_ACTION = 3; + public static final int CREATE_URL_WITH_CONTEXT_ACTION = 4; + public static final int DELETE_FILE_ACTION = 5; + public static final int EXEC_ACTION = 6; + public static final int FILE_EXISTS_ACTION = 7; + public static final int FILE_IS_DIRECTORY_ACTION = 8; + public static final int FOR_NAME_ACTION = 9; + public static final int GET_ABSOLUTE_PATH_ACTION = 10; + public static final int GET_CONSTRUCTOR_ACTION = 11; + public static final int GET_DECLARED_CONSTRUCTOR_ACTION = 12; + public static final int GET_DECLARED_METHOD_ACTION = 13; + public static final int GET_FIELD_ACTION = 14; + public static final int GET_FILE_INPUT_ACTION = 15; + public static final int GET_FILE_OUTPUT_ACTION = 16; + public static final int TO_URI_ACTION = 17; + public static final int GET_METHOD_ACTION = 18; + public static final int GET_POLICY_ACTION = 19; + public static final int GET_PROPERTY_ACTION = 20; + public static final int GET_PARENT_CLASS_LOADER_ACTION = 21; + public static final int GET_SYSTEM_CLASS_LOADER_ACTION = 22; + public static final int GET_URL_INPUT_ACTION = 23; + public static final int INVOKE_CONSTRUCTOR_ACTION = 24; + public static final int INVOKE_DIRECTMETHOD_ACTION = 25; + public static final int INVOKE_METHOD_ACTION = 26; + public static final int LIST_DIRECTORY_ACTION = 27; + public static final int MAKE_DIRECTORIES_ACTION = 28; + public static final int MAKE_DIRECTORY_ACTION = 29; + public static final int OPEN_ZIPFILE_ACTION = 30; + public static final int OPEN_URLCONNECTION_ACTION = 31; + public static final int RENAME_FILE_ACTION = 32; + public static final int SET_ACCESSIBLE_ACTION = 33; + public static final int START_ACTIVATOR_ACTION = 34; + public static final int STOP_ACTIVATOR_ACTION = 35; + public static final int SWAP_FIELD_ACTION = 36; + public static final int SYSTEM_EXIT_ACTION = 37; + public static final int FLUSH_FIELD_ACTION = 38; + public static final int GET_CLASS_LOADER_ACTION = 39; + public static final int INVOKE_BUNDLE_FIND_HOOK = 40; + public static final int INVOKE_BUNDLE_EVENT_HOOK = 41; + public static final int INVOKE_WEAVING_HOOK = 42; + public static final int INVOKE_SERVICE_EVENT_HOOK = 43; + public static final int INVOKE_SERVICE_FIND_HOOK = 44; + public static final int INVOKE_SERVICE_LISTENER_HOOK_ADDED = 45; + public static final int INVOKE_SERVICE_LISTENER_HOOK_REMOVED = 46; + public static final int INVOKE_SERVICE_EVENT_LISTENER_HOOK = 47; + public static final int INVOKE_RESOLVER_HOOK_FACTORY = 48; + public static final int INVOKE_RESOLVER_HOOK_RESOLVABLE = 49; + public static final int INVOKE_RESOLVER_HOOK_SINGLETON = 50; + public static final int INVOKE_RESOLVER_HOOK_MATCHES = 51; + public static final int INVOKE_RESOLVER_HOOK_END = 52; + + private int m_action = -1; + private Object m_arg1 = null; + private Object m_arg2 = null; + private Object m_arg3 = null; + private Object m_arg4 = null; + private Object m_arg5 = null; + private Object m_arg6 = null; + + public void set(int action) + { + m_action = action; + } + + public void set(int action, Object arg1) + { + m_action = action; + m_arg1 = arg1; + } + + public void set(int action, Object arg1, Object arg2) + { + m_action = action; + m_arg1 = arg1; + m_arg2 = arg2; + } + + public void set(int action, Object arg1, Object arg2, Object arg3) + { + m_action = action; + m_arg1 = arg1; + m_arg2 = arg2; + m_arg3 = arg3; + } + + public void set(int action, Object arg1, Object arg2, Object arg3, + Object arg4) + { + m_action = action; + m_arg1 = arg1; + m_arg2 = arg2; + m_arg3 = arg3; + m_arg4 = arg4; + } + + public void set(int action, Object arg1, Object arg2, Object arg3, + Object arg4, Object arg5) + { + m_action = action; + m_arg1 = arg1; + m_arg2 = arg2; + m_arg3 = arg3; + m_arg4 = arg4; + m_arg5 = arg5; + } + + public void set(int action, Object arg1, Object arg2, Object arg3, + Object arg4, Object arg5, Object arg6) + { + m_action = action; + m_arg1 = arg1; + m_arg2 = arg2; + m_arg3 = arg3; + m_arg4 = arg4; + m_arg5 = arg5; + m_arg6 = arg6; + } + + private void unset() + { + m_action = -1; + m_arg1 = null; + m_arg2 = null; + m_arg3 = null; + m_arg4 = null; + m_arg5 = null; + m_arg6 = null; + } + + public Object run() throws Exception + { + int action = m_action; + Object arg1 = m_arg1; + Object arg2 = m_arg2; + Object arg3 = m_arg3; + Object arg4 = m_arg4; + Object arg5 = m_arg5; + Object arg6 = m_arg6; + + unset(); + + switch (action) + { + case INITIALIZE_CONTEXT_ACTION: + return AccessController.getContext(); + case ADD_EXTENSION_URL_ACTION: + Method addURL = + URLClassLoader.class.getDeclaredMethod("addURL", + new Class[] {URL.class}); + addURL.setAccessible(true); + addURL.invoke(arg2, new Object[]{arg1}); + return null; + case CREATE_TMPFILE_ACTION: + return File.createTempFile((String) arg1, (String) arg2, (File) arg3); + case CREATE_URL_ACTION: + return new URL((String) arg1, (String) arg2, + ((Integer) arg3).intValue(), (String) arg4, + (URLStreamHandler) arg5); + case CREATE_URL_WITH_CONTEXT_ACTION: + return new URL((URL) arg1, (String) arg2, (URLStreamHandler) arg3); + case DELETE_FILE_ACTION: + return ((File) arg1).delete() ? Boolean.TRUE : Boolean.FALSE; + case EXEC_ACTION: + return Runtime.getRuntime().exec((String) arg1); + case FILE_EXISTS_ACTION: + return ((File) arg1).exists() ? Boolean.TRUE : Boolean.FALSE; + case FILE_IS_DIRECTORY_ACTION: + return ((File) arg1).isDirectory() ? Boolean.TRUE : Boolean.FALSE; + case FOR_NAME_ACTION: + return Class.forName((String) arg1); + case GET_ABSOLUTE_PATH_ACTION: + return ((File) arg1).getAbsolutePath(); + case GET_CONSTRUCTOR_ACTION: + return ((Class) arg1).getConstructor((Class[]) arg2); + case GET_DECLARED_CONSTRUCTOR_ACTION: + return ((Class) arg1).getDeclaredConstructor((Class[]) arg2); + case GET_DECLARED_METHOD_ACTION: + return ((Class) arg1).getDeclaredMethod((String) arg2, (Class[]) arg3); + case GET_FIELD_ACTION: + Field field = ((Class) arg1).getDeclaredField((String) arg2); + field.setAccessible(true); + return field.get(arg3); + case GET_FILE_INPUT_ACTION: + return new FileInputStream((File) arg1); + case GET_FILE_OUTPUT_ACTION: + return new FileOutputStream((File) arg1); + case TO_URI_ACTION: + return ((File) arg1).toURI(); + case GET_METHOD_ACTION: + return ((Class) arg1).getMethod((String) arg2, (Class[]) arg3); + case GET_POLICY_ACTION: + return Policy.getPolicy(); + case GET_PROPERTY_ACTION: + return System.getProperty((String) arg1, (String) arg2); + case GET_PARENT_CLASS_LOADER_ACTION: + return ((ClassLoader) arg1).getParent(); + case GET_SYSTEM_CLASS_LOADER_ACTION: + return ClassLoader.getSystemClassLoader(); + case GET_URL_INPUT_ACTION: + return ((URLConnection) arg1).getInputStream(); + case INVOKE_CONSTRUCTOR_ACTION: + return ((Constructor) arg1).newInstance((Object[]) arg2); + case INVOKE_DIRECTMETHOD_ACTION: + return ((Method) arg1).invoke(arg2, (Object[]) arg3); + case INVOKE_METHOD_ACTION: + ((Method) arg1).setAccessible(true); + return ((Method) arg1).invoke(arg2, (Object[]) arg3); + case LIST_DIRECTORY_ACTION: + return ((File) arg1).listFiles(); + case MAKE_DIRECTORIES_ACTION: + return ((File) arg1).mkdirs() ? Boolean.TRUE : Boolean.FALSE; + case MAKE_DIRECTORY_ACTION: + return ((File) arg1).mkdir() ? Boolean.TRUE : Boolean.FALSE; + case OPEN_ZIPFILE_ACTION: + return new ZipFile((File) arg1); + case OPEN_URLCONNECTION_ACTION: + return ((URL) arg1).openConnection(); + case RENAME_FILE_ACTION: + return ((File) arg1).renameTo((File) arg2) ? Boolean.TRUE : Boolean.FALSE; + case SET_ACCESSIBLE_ACTION: + ((AccessibleObject) arg1).setAccessible(true); + return null; + case START_ACTIVATOR_ACTION: + ((BundleActivator) arg1).start((BundleContext) arg2); + return null; + case STOP_ACTIVATOR_ACTION: + ((BundleActivator) arg1).stop((BundleContext) arg2); + return null; + case SWAP_FIELD_ACTION: + return _swapStaticFieldIfNotClass((Class) arg1, + (Class) arg2, (Class) arg3, (String) arg4); + case SYSTEM_EXIT_ACTION: + System.exit(((Integer) arg1).intValue()); + case FLUSH_FIELD_ACTION: + _flush(((Class) arg1), arg2); + return null; + case GET_CLASS_LOADER_ACTION: + return ((Class) arg1).getClassLoader(); + /* case INVOKE_BUNDLE_FIND_HOOK: + ((org.osgi.framework.hooks.bundle.FindHook) arg1).find( + (BundleContext) arg2, (Collection) arg3); + return null; + case INVOKE_BUNDLE_EVENT_HOOK: + ((org.osgi.framework.hooks.bundle.EventHook) arg1).event( + (BundleEvent) arg2, (Collection) arg3); + return null; + case INVOKE_WEAVING_HOOK: + ((org.osgi.framework.hooks.weaving.WeavingHook) arg1).weave( + (org.osgi.framework.hooks.weaving.WovenClass) arg2); + return null; + case INVOKE_SERVICE_EVENT_HOOK: + ((org.osgi.framework.hooks.service.EventHook) arg1).event( + (ServiceEvent) arg2, (Collection) arg3); + return null; + case INVOKE_SERVICE_FIND_HOOK: + ((org.osgi.framework.hooks.service.FindHook) arg1).find( + (BundleContext) arg2, (String) arg3, (String) arg4, + ((Boolean) arg5).booleanValue(), + (Collection>) arg6); + return null; + case INVOKE_SERVICE_LISTENER_HOOK_ADDED: + ((org.osgi.framework.hooks.service.ListenerHook) arg1).added( + (Collection) arg2); + return null; + case INVOKE_SERVICE_LISTENER_HOOK_REMOVED: + ((org.osgi.framework.hooks.service.ListenerHook) arg1).removed( + (Collection) arg2); + return null; + case INVOKE_SERVICE_EVENT_LISTENER_HOOK: + ((org.osgi.framework.hooks.service.EventListenerHook) arg1).event( + (ServiceEvent) arg2, + (Map>) arg3); + return null; + case INVOKE_RESOLVER_HOOK_FACTORY: + return ((org.osgi.framework.hooks.resolver.ResolverHookFactory) arg1).begin( + (Collection) arg2); + case INVOKE_RESOLVER_HOOK_RESOLVABLE: + ((org.osgi.framework.hooks.resolver.ResolverHook) arg1).filterResolvable( + (Collection) arg2); + return null; + case INVOKE_RESOLVER_HOOK_SINGLETON: + ((org.osgi.framework.hooks.resolver.ResolverHook) arg1) + .filterSingletonCollisions( + (BundleCapability) arg2, + (Collection) arg3); + return null; + case INVOKE_RESOLVER_HOOK_MATCHES: + ((org.osgi.framework.hooks.resolver.ResolverHook) arg1).filterMatches( + (BundleRequirement) arg2, + (Collection) arg3); + return null; + case INVOKE_RESOLVER_HOOK_END: + ((org.osgi.framework.hooks.resolver.ResolverHook) arg1).end(); + return null;*/ + } + + return null; + } + } +} \ No newline at end of file Added: incubator/ace/trunk/ace-deployment-verifier/src/main/java/org/apache/felix/framework/util/StringComparator.java URL: http://svn.apache.org/viewvc/incubator/ace/trunk/ace-deployment-verifier/src/main/java/org/apache/felix/framework/util/StringComparator.java?rev=1170188&view=auto ============================================================================== --- incubator/ace/trunk/ace-deployment-verifier/src/main/java/org/apache/felix/framework/util/StringComparator.java (added) +++ incubator/ace/trunk/ace-deployment-verifier/src/main/java/org/apache/felix/framework/util/StringComparator.java Tue Sep 13 14:06:20 2011 @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 + * + * http://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 org.apache.felix.framework.util; + +import java.util.Comparator; + +public class StringComparator implements Comparator +{ + private final boolean m_isCaseSensitive; + + public StringComparator(boolean b) + { + m_isCaseSensitive = b; + } + + public int compare(Object o1, Object o2) + { + if (m_isCaseSensitive) + { + return o1.toString().compareTo(o2.toString()); + } + else + { + return o1.toString().compareToIgnoreCase(o2.toString()); + } + } + + public boolean isCaseSensitive() + { + return m_isCaseSensitive; + } +} \ No newline at end of file Added: incubator/ace/trunk/ace-deployment-verifier/src/main/java/org/apache/felix/framework/util/Util.java URL: http://svn.apache.org/viewvc/incubator/ace/trunk/ace-deployment-verifier/src/main/java/org/apache/felix/framework/util/Util.java?rev=1170188&view=auto ============================================================================== --- incubator/ace/trunk/ace-deployment-verifier/src/main/java/org/apache/felix/framework/util/Util.java (added) +++ incubator/ace/trunk/ace-deployment-verifier/src/main/java/org/apache/felix/framework/util/Util.java Tue Sep 13 14:06:20 2011 @@ -0,0 +1,649 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 + * + * http://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 org.apache.felix.framework.util; + +import java.io.*; +import java.net.URL; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import org.apache.felix.framework.Logger; +import org.apache.felix.framework.capabilityset.CapabilitySet; +import org.apache.felix.framework.wiring.BundleCapabilityImpl; +import org.apache.felix.framework.wiring.BundleRequirementImpl; + +import org.osgi.framework.Bundle; +import org.osgi.framework.Constants; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.wiring.BundleCapability; +import org.osgi.framework.wiring.BundleRequirement; +import org.osgi.framework.wiring.BundleRevision; +import org.osgi.framework.wiring.BundleWire; +import org.osgi.framework.wiring.BundleWiring; + +public class Util +{ + /** + * The default name used for the default configuration properties file. + **/ + private static final String DEFAULT_PROPERTIES_FILE = "default.properties"; + + public static String getDefaultProperty(Logger logger, String name) + { + String value = null; + + URL propURL = Util.class.getClassLoader().getResource(DEFAULT_PROPERTIES_FILE); + if (propURL != null) + { + InputStream is = null; + try + { + // Load properties from URL. + is = propURL.openConnection().getInputStream(); + Properties props = new Properties(); + props.load(is); + is.close(); + // Perform variable substitution for property. + value = props.getProperty(name); + value = (value != null) + ? Util.substVars(value, name, null, props) + : null; + } + catch (Exception ex) + { + // Try to close input stream if we have one. + try + { + if (is != null) is.close(); + } + catch (IOException ex2) + { + // Nothing we can do. + } + + logger.log( + Logger.LOG_ERROR, "Unable to load any configuration properties.", ex); + } + } + return value; + } + + /** + * Converts a revision identifier to a bundle identifier. Revision IDs + * are typically <bundle-id>.<revision>; this + * method returns only the portion corresponding to the bundle ID. + **/ + public static long getBundleIdFromRevisionId(String id) + { + try + { + String bundleId = (id.indexOf('.') >= 0) + ? id.substring(0, id.indexOf('.')) : id; + return Long.parseLong(bundleId); + } + catch (NumberFormatException ex) + { + return -1; + } + } + + /** + * Converts a module identifier to a bundle identifier. Module IDs + * are typically <bundle-id>.<revision>; this + * method returns only the portion corresponding to the revision. + **/ + public static int getModuleRevisionFromModuleId(String id) + { + try + { + int index = id.indexOf('.'); + if (index >= 0) + { + return Integer.parseInt(id.substring(index + 1)); + } + } + catch (NumberFormatException ex) + { + } + return -1; + } + + public static String getClassName(String className) + { + if (className == null) + { + className = ""; + } + return (className.lastIndexOf('.') < 0) + ? "" : className.substring(className.lastIndexOf('.') + 1); + } + + public static String getClassPackage(String className) + { + if (className == null) + { + className = ""; + } + return (className.lastIndexOf('.') < 0) + ? "" : className.substring(0, className.lastIndexOf('.')); + } + + public static String getResourcePackage(String resource) + { + if (resource == null) + { + resource = ""; + } + // NOTE: The package of a resource is tricky to determine since + // resources do not follow the same naming conventions as classes. + // This code is pessimistic and assumes that the package of a + // resource is everything up to the last '/' character. By making + // this choice, it will not be possible to load resources from + // imports using relative resource names. For example, if a + // bundle exports "foo" and an importer of "foo" tries to load + // "/foo/bar/myresource.txt", this will not be found in the exporter + // because the following algorithm assumes the package name is + // "foo.bar", not just "foo". This only affects imported resources, + // local resources will work as expected. + String pkgName = (resource.startsWith("/")) ? resource.substring(1) : resource; + pkgName = (pkgName.lastIndexOf('/') < 0) + ? "" : pkgName.substring(0, pkgName.lastIndexOf('/')); + pkgName = pkgName.replace('/', '.'); + return pkgName; + } + + /** + *

+ * This is a simple utility class that attempts to load the named + * class using the class loader of the supplied class or + * the class loader of one of its super classes or their implemented + * interfaces. This is necessary during service registration to test + * whether a given service object implements its declared service + * interfaces. + *

+ *

+ * To perform this test, the framework must try to load + * the classes associated with the declared service interfaces, so + * it must choose a class loader. The class loader of the registering + * bundle cannot be used, since this disallows third parties to + * register service on behalf of another bundle. Consequently, the + * class loader of the service object must be used. However, this is + * also not sufficient since the class loader of the service object + * may not have direct access to the class in question. + *

+ *

+ * The service object's class loader may not have direct access to + * its service interface if it extends a super class from another + * bundle which implements the service interface from an imported + * bundle or if it implements an extension of the service interface + * from another bundle which imports the base interface from another + * bundle. In these cases, the service object's class loader only has + * access to the super class's class or the extended service interface, + * respectively, but not to the actual service interface. + *

+ *

+ * Thus, it is necessary to not only try to load the service interface + * class from the service object's class loader, but from the class + * loaders of any interfaces it implements and the class loaders of + * all super classes. + *

+ * @param svcObj the class that is the root of the search. + * @param name the name of the class to load. + * @return the loaded class or null if it could not be + * loaded. + **/ + public static Class loadClassUsingClass(Class clazz, String name, SecureAction action) + { + Class loadedClass = null; + + while (clazz != null) + { + // Get the class loader of the current class object. + ClassLoader loader = action.getClassLoader(clazz); + // A null class loader represents the system class loader. + loader = (loader == null) ? action.getSystemClassLoader() : loader; + try + { + return loader.loadClass(name); + } + catch (ClassNotFoundException ex) + { + // Ignore and try interface class loaders. + } + + // Try to see if we can load the class from + // one of the class's implemented interface + // class loaders. + Class[] ifcs = clazz.getInterfaces(); + for (int i = 0; i < ifcs.length; i++) + { + loadedClass = loadClassUsingClass(ifcs[i], name, action); + if (loadedClass != null) + { + return loadedClass; + } + } + + // Try to see if we can load the class from + // the super class class loader. + clazz = clazz.getSuperclass(); + } + + return null; + } + + /** + * This method determines if the requesting bundle is able to cast + * the specified service reference based on class visibility rules + * of the underlying modules. + * @param requester The bundle requesting the service. + * @param ref The service in question. + * @return true if the requesting bundle is able to case + * the service object to a known type. + **/ + public static boolean isServiceAssignable(Bundle requester, ServiceReference ref) + { + // Boolean flag. + boolean allow = true; + // Get the service's objectClass property. + String[] objectClass = (String[]) ref.getProperty(FelixConstants.OBJECTCLASS); + + // The the service reference is not assignable when the requesting + // bundle is wired to a different version of the service object. + // NOTE: We are pessimistic here, if any class in the service's + // objectClass is not usable by the requesting bundle, then we + // disallow the service reference. + for (int classIdx = 0; (allow) && (classIdx < objectClass.length); classIdx++) + { + if (!ref.isAssignableTo(requester, objectClass[classIdx])) + { + allow = false; + } + } + return allow; + } + + public static BundleCapability getSatisfyingCapability( + BundleRevision br, BundleRequirementImpl req) + { + List caps = (br.getWiring() != null) + ? br.getWiring().getCapabilities(null) + : br.getDeclaredCapabilities(null); + if (caps != null) + { + for (BundleCapability cap : caps) + { + if (cap.getNamespace().equals(req.getNamespace()) + && CapabilitySet.matches((BundleCapabilityImpl) cap, req.getFilter())) + { + return cap; + } + } + } + return null; + } + + /** + * Returns all the capabilities from a module that has a specified namespace. + * + * @param br module providing capabilities + * @param namespace capability namespace + * @return array of matching capabilities or empty if none found + */ + public static List getCapabilityByNamespace( + BundleRevision br, String namespace) + { + final List matching = new ArrayList(); + final List caps = (br.getWiring() != null) + ? br.getWiring().getCapabilities(null) + : br.getDeclaredCapabilities(null); + if (caps != null) + { + for (BundleCapability cap : caps) + { + if (cap.getNamespace().equals(namespace)) + { + matching.add(cap); + } + } + } + return matching; + } + + public static List getDynamicRequirements( + List reqs) + { + List result = new ArrayList(); + if (reqs != null) + { + for (BundleRequirement req : reqs) + { + String resolution = req.getDirectives().get(Constants.RESOLUTION_DIRECTIVE); + if ((resolution != null) && resolution.equals("dynamic")) + { + result.add(req); + } + } + } + return result; + } + + public static BundleWire getWire(BundleRevision br, String name) + { + if (br.getWiring() != null) + { + List wires = br.getWiring().getRequiredWires(null); + if (wires != null) + { + for (BundleWire w : wires) + { + if (w.getCapability().getNamespace() + .equals(BundleRevision.PACKAGE_NAMESPACE) && + w.getCapability().getAttributes() + .get(BundleRevision.PACKAGE_NAMESPACE).equals(name)) + { + return w; + } + } + } + } + return null; + } + + private static final byte encTab[] = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, + 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, + 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x61, 0x62, 0x63, 0x64, + 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, + 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x30, 0x31, + 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2b, 0x2f }; + + private static final byte decTab[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, + -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, + -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, -1, -1, -1, -1, -1 }; + + public static String base64Encode(String s) throws IOException + { + return encode(s.getBytes(), 0); + } + + /** + * Encode a raw byte array to a Base64 String. + * + * @param in Byte array to encode. + * @param len Length of Base64 lines. 0 means no line breaks. + **/ + public static String encode(byte[] in, int len) throws IOException + { + ByteArrayOutputStream baos = null; + ByteArrayInputStream bais = null; + try + { + baos = new ByteArrayOutputStream(); + bais = new ByteArrayInputStream(in); + encode(bais, baos, len); + // ASCII byte array to String + return (new String(baos.toByteArray())); + } + finally + { + if (baos != null) + { + baos.close(); + } + if (bais != null) + { + bais.close(); + } + } + } + + public static void encode(InputStream in, OutputStream out, int len) + throws IOException + { + + // Check that length is a multiple of 4 bytes + if (len % 4 != 0) + { + throw new IllegalArgumentException("Length must be a multiple of 4"); + } + + // Read input stream until end of file + int bits = 0; + int nbits = 0; + int nbytes = 0; + int b; + + while ((b = in.read()) != -1) + { + bits = (bits << 8) | b; + nbits += 8; + while (nbits >= 6) + { + nbits -= 6; + out.write(encTab[0x3f & (bits >> nbits)]); + nbytes++; + // New line + if (len != 0 && nbytes >= len) + { + out.write(0x0d); + out.write(0x0a); + nbytes -= len; + } + } + } + + switch (nbits) + { + case 2: + out.write(encTab[0x3f & (bits << 4)]); + out.write(0x3d); // 0x3d = '=' + out.write(0x3d); + break; + case 4: + out.write(encTab[0x3f & (bits << 2)]); + out.write(0x3d); + break; + } + + if (len != 0) + { + if (nbytes != 0) + { + out.write(0x0d); + out.write(0x0a); + } + out.write(0x0d); + out.write(0x0a); + } + } + + + private static final String DELIM_START = "${"; + private static final String DELIM_STOP = "}"; + + /** + *

+ * This method performs property variable substitution on the + * specified value. If the specified value contains the syntax + * ${<prop-name>}, where <prop-name> + * refers to either a configuration property or a system property, + * then the corresponding property value is substituted for the variable + * placeholder. Multiple variable placeholders may exist in the + * specified value as well as nested variable placeholders, which + * are substituted from inner most to outer most. Configuration + * properties override system properties. + *

+ * @param val The string on which to perform property substitution. + * @param currentKey The key of the property being evaluated used to + * detect cycles. + * @param cycleMap Map of variable references used to detect nested cycles. + * @param configProps Set of configuration properties. + * @return The value of the specified string after system property substitution. + * @throws IllegalArgumentException If there was a syntax error in the + * property placeholder syntax or a recursive variable reference. + **/ + public static String substVars(String val, String currentKey, + Map cycleMap, Properties configProps) + throws IllegalArgumentException + { + // If there is currently no cycle map, then create + // one for detecting cycles for this invocation. + if (cycleMap == null) + { + cycleMap = new HashMap(); + } + + // Put the current key in the cycle map. + cycleMap.put(currentKey, currentKey); + + // Assume we have a value that is something like: + // "leading ${foo.${bar}} middle ${baz} trailing" + + // Find the first ending '}' variable delimiter, which + // will correspond to the first deepest nested variable + // placeholder. + int stopDelim = -1; + int startDelim = -1; + + do + { + stopDelim = val.indexOf(DELIM_STOP, stopDelim + 1); + // If there is no stopping delimiter, then just return + // the value since there is no variable declared. + if (stopDelim < 0) + { + return val; + } + // Try to find the matching start delimiter by + // looping until we find a start delimiter that is + // greater than the stop delimiter we have found. + startDelim = val.indexOf(DELIM_START); + // If there is no starting delimiter, then just return + // the value since there is no variable declared. + if (startDelim < 0) + { + return val; + } + while (stopDelim >= 0) + { + int idx = val.indexOf(DELIM_START, startDelim + DELIM_START.length()); + if ((idx < 0) || (idx > stopDelim)) + { + break; + } + else if (idx < stopDelim) + { + startDelim = idx; + } + } + } + while ((startDelim > stopDelim) && (stopDelim >= 0)); + + // At this point, we have found a variable placeholder so + // we must perform a variable substitution on it. + // Using the start and stop delimiter indices, extract + // the first, deepest nested variable placeholder. + String variable = + val.substring(startDelim + DELIM_START.length(), stopDelim); + + // Verify that this is not a recursive variable reference. + if (cycleMap.get(variable) != null) + { + throw new IllegalArgumentException( + "recursive variable reference: " + variable); + } + + // Get the value of the deepest nested variable placeholder. + // Try to configuration properties first. + String substValue = (configProps != null) + ? configProps.getProperty(variable, null) + : null; + if (substValue == null) + { + // Ignore unknown property values. + substValue = System.getProperty(variable, ""); + } + + // Remove the found variable from the cycle map, since + // it may appear more than once in the value and we don't + // want such situations to appear as a recursive reference. + cycleMap.remove(variable); + + // Append the leading characters, the substituted value of + // the variable, and the trailing characters to get the new + // value. + val = val.substring(0, startDelim) + + substValue + + val.substring(stopDelim + DELIM_STOP.length(), val.length()); + + // Now perform substitution again, since there could still + // be substitutions to make. + val = substVars(val, currentKey, cycleMap, configProps); + + // Return the value. + return val; + } + + /** + * Checks if the provided module definition declares a fragment host. + * + * @param module the module to check + * @return true if the module declares a fragment host, false + * otherwise. + */ + public static boolean isFragment(BundleRevision revision) + { + return ((revision.getTypes() & BundleRevision.TYPE_FRAGMENT) > 0); + } + + public static List getFragments(BundleWiring wiring) + { + List fragments = Collections.EMPTY_LIST; + if (wiring != null) + { + List wires = wiring.getProvidedWires(null); + if (wires != null) + { + for (BundleWire w : wires) + { + if (w.getCapability().getNamespace() + .equals(BundleRevision.HOST_NAMESPACE)) + { + // Create array list if needed. + if (fragments.isEmpty()) + { + fragments = new ArrayList(); + } + fragments.add(w.getRequirerWiring().getRevision()); + } + } + } + } + return fragments; + } +} \ No newline at end of file