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 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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334
|
/*******************************************************************************
* Copyright (c) 2005, 2010 IBM Corporation and others.
* 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.osgi.baseadaptor;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.*;
import org.eclipse.osgi.baseadaptor.hooks.*;
import org.eclipse.osgi.framework.adaptor.*;
import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
import org.eclipse.osgi.util.ManifestElement;
/**
* The hook registry is used to store all the hooks which are
* configured by the hook configurators.
* @see HookConfigurator
* @since 3.2
*/
public final class HookRegistry {
/**
* The hook configurators properties file ("hookconfigurators.properties") <p>
* A framework extension may supply a hook configurators properties file to specify a
* list of hook configurators.
* @see #HOOK_CONFIGURATORS
*/
public static final String HOOK_CONFIGURATORS_FILE = "hookconfigurators.properties"; //$NON-NLS-1$
/**
* The hook configurators property key ("hookconfigurators.properties") used in
* a hook configurators properties file to specify a comma separated list of fully
* qualified hook configurator classes.
*/
public static final String HOOK_CONFIGURATORS = "hook.configurators"; //$NON-NLS-1$
/**
* A system property ("osgi.hook.configurators.include") used to add additional
* hook configurators. This is helpful for configuring optional hook configurators.
*/
public static final String PROP_HOOK_CONFIGURATORS_INCLUDE = "osgi.hook.configurators.include"; //$NON-NLS-1$
/**
* A system property ("osgi.hook.configurators.exclude") used to exclude
* any hook configurators. This is helpful for disabling hook
* configurators that is specified in hook configurator properties files.
*/
public static final String PROP_HOOK_CONFIGURATORS_EXCLUDE = "osgi.hook.configurators.exclude"; //$NON-NLS-1$
/**
* A system property ("osgi.hook.configurators") used to specify the list
* of hook configurators. If this property is set then the list of configurators
* specified will be the only configurators used.
*/
public static final String PROP_HOOK_CONFIGURATORS = "osgi.hook.configurators"; //$NON-NLS-1$
private static final String BUILTIN_HOOKS = "builtin.hooks"; //$NON-NLS-1$
private BaseAdaptor adaptor;
private boolean readonly = false;
private AdaptorHook[] adaptorHooks = new AdaptorHook[0];
private BundleWatcher[] watchers = new BundleWatcher[0];
private ClassLoadingHook[] classLoadingHooks = new ClassLoadingHook[0];
private ClassLoadingStatsHook[] classLoadingStatsHooks = new ClassLoadingStatsHook[0];
private ClassLoaderDelegateHook[] classLoaderDelegateHooks = new ClassLoaderDelegateHook[0];
private StorageHook[] storageHooks = new StorageHook[0];
private BundleFileFactoryHook[] bundleFileFactoryHooks = new BundleFileFactoryHook[0];
private BundleFileWrapperFactoryHook[] bundleFileWrapperFactoryHooks = new BundleFileWrapperFactoryHook[0];
public HookRegistry(BaseAdaptor adaptor) {
this.adaptor = adaptor;
}
/**
* Initializes the hook configurators. The following steps are used to initialize the hook configurators. <p>
* 1. Get a list of hook configurators from all hook configurators properties files on the classpath,
* add this list to the overall list of hook configurators, remove duplicates. <p>
* 2. Get a list of hook configurators from the ("osgi.hook.configurators.include") system property
* and add this list to the overall list of hook configurators, remove duplicates. <p>
* 3. Get a list of hook configurators from the ("osgi.hook.configurators.exclude") system property
* and remove this list from the overall list of hook configurators. <p>
* 4. Load each hook configurator class, create a new instance, then call the {@link HookConfigurator#addHooks(HookRegistry)} method <p>
* 5. Set this HookRegistry object to read only to prevent any other hooks from being added. <p>
* @return an array of error log entries that occurred while initializing the hooks
*/
public FrameworkLogEntry[] initialize() {
List<String> configurators = new ArrayList<String>(5);
List<FrameworkLogEntry> errors = new ArrayList<FrameworkLogEntry>(0); // optimistic that no errors will occur
mergeFileHookConfigurators(configurators, errors);
mergePropertyHookConfigurators(configurators);
loadConfigurators(configurators, errors);
// set to read-only
readonly = true;
return errors.toArray(new FrameworkLogEntry[errors.size()]);
}
private void mergeFileHookConfigurators(List<String> configuratorList, List<FrameworkLogEntry> errors) {
ClassLoader cl = getClass().getClassLoader();
// get all hook configurators files in your classloader delegation
Enumeration<URL> hookConfigurators;
try {
hookConfigurators = cl != null ? cl.getResources(HookRegistry.HOOK_CONFIGURATORS_FILE) : ClassLoader.getSystemResources(HookRegistry.HOOK_CONFIGURATORS_FILE);
} catch (IOException e) {
errors.add(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, "getResources error on " + HookRegistry.HOOK_CONFIGURATORS_FILE, 0, e, null)); //$NON-NLS-1$
return;
}
int curBuiltin = 0;
while (hookConfigurators.hasMoreElements()) {
URL url = hookConfigurators.nextElement();
InputStream input = null;
try {
// check each file for a hook.configurators property
Properties configuratorProps = new Properties();
input = url.openStream();
configuratorProps.load(input);
String hooksValue = configuratorProps.getProperty(HOOK_CONFIGURATORS);
if (hooksValue == null)
continue;
boolean builtin = Boolean.valueOf(configuratorProps.getProperty(BUILTIN_HOOKS)).booleanValue();
String[] configurators = ManifestElement.getArrayFromList(hooksValue, ","); //$NON-NLS-1$
for (int i = 0; i < configurators.length; i++)
if (!configuratorList.contains(configurators[i])) {
if (builtin) // make sure the built-in configurators are listed first (bug 170881)
configuratorList.add(curBuiltin++, configurators[i]);
else
configuratorList.add(configurators[i]);
}
} catch (IOException e) {
errors.add(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, "error loading: " + url.toExternalForm(), 0, e, null)); //$NON-NLS-1$
// ignore and continue to next URL
} finally {
if (input != null)
try {
input.close();
} catch (IOException e) {
// do nothing
}
}
}
}
private void mergePropertyHookConfigurators(List<String> configuratorList) {
// see if there is a configurators list
String[] configurators = ManifestElement.getArrayFromList(FrameworkProperties.getProperty(HookRegistry.PROP_HOOK_CONFIGURATORS), ","); //$NON-NLS-1$
if (configurators.length > 0) {
configuratorList.clear(); // clear the list, we are only going to use the configurators from the list
for (int i = 0; i < configurators.length; i++)
if (!configuratorList.contains(configurators[i]))
configuratorList.add(configurators[i]);
return; // don't do anything else
}
// Make sure the configurators from the include property are in the list
String[] includeConfigurators = ManifestElement.getArrayFromList(FrameworkProperties.getProperty(HookRegistry.PROP_HOOK_CONFIGURATORS_INCLUDE), ","); //$NON-NLS-1$
for (int i = 0; i < includeConfigurators.length; i++)
if (!configuratorList.contains(includeConfigurators[i]))
configuratorList.add(includeConfigurators[i]);
// Make sure the configurators from the exclude property are no in the list
String[] excludeHooks = ManifestElement.getArrayFromList(FrameworkProperties.getProperty(HookRegistry.PROP_HOOK_CONFIGURATORS_EXCLUDE), ","); //$NON-NLS-1$
for (int i = 0; i < excludeHooks.length; i++)
configuratorList.remove(excludeHooks[i]);
}
private void loadConfigurators(List<String> configurators, List<FrameworkLogEntry> errors) {
for (Iterator<String> iHooks = configurators.iterator(); iHooks.hasNext();) {
String hookName = iHooks.next();
try {
Class<?> clazz = Class.forName(hookName);
HookConfigurator configurator = (HookConfigurator) clazz.newInstance();
configurator.addHooks(this);
} catch (Throwable t) {
// We expect the follow exeptions may happen; but we need to catch all here
// ClassNotFoundException
// IllegalAccessException
// InstantiationException
// ClassCastException
errors.add(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, "error loading hook: " + hookName, 0, t, null)); //$NON-NLS-1$
}
}
}
/**
* Returns the list of configured adaptor hooks.
* @return the list of configured adaptor hooks.
*/
public AdaptorHook[] getAdaptorHooks() {
return adaptorHooks;
}
/**
* Returns the list of configured bundle watchers.
* @return the list of configured bundle watchers.
*/
public BundleWatcher[] getWatchers() {
return watchers;
}
/**
* Returns the list of configured class loading hooks.
* @return the list of configured class loading hooks.
*/
public ClassLoadingHook[] getClassLoadingHooks() {
return classLoadingHooks;
}
/**
* Returns the list of configured class loading stats hooks.
* @return the list of configured class loading stats hooks.
*/
public ClassLoadingStatsHook[] getClassLoadingStatsHooks() {
return classLoadingStatsHooks;
}
/**
* Returns the list of configured class loader delegate hooks.
* @return the list of configured class loader delegate hooks.
*/
public ClassLoaderDelegateHook[] getClassLoaderDelegateHooks() {
return classLoaderDelegateHooks;
}
/**
* Returns the list of configured storage hooks.
* @return the list of configured storage hooks.
*/
public StorageHook[] getStorageHooks() {
return storageHooks;
}
/**
* Returns the list of configured bundle file factories.
* @return the list of configured bundle file factories.
*/
public BundleFileFactoryHook[] getBundleFileFactoryHooks() {
return bundleFileFactoryHooks;
}
/**
* Returns the configured bundle file wrapper factories
* @return the configured bundle file wrapper factories
*/
public BundleFileWrapperFactoryHook[] getBundleFileWrapperFactoryHooks() {
return bundleFileWrapperFactoryHooks;
}
/**
* Adds a adaptor hook to this hook registry.
* @param adaptorHook an adaptor hook object.
*/
public void addAdaptorHook(AdaptorHook adaptorHook) {
adaptorHooks = (AdaptorHook[]) add(adaptorHook, adaptorHooks, new AdaptorHook[adaptorHooks.length + 1]);
}
/**
* Adds a bundle watcher to this hook registry.
* @param watcher a bundle watcher object.
*/
public void addWatcher(BundleWatcher watcher) {
watchers = (BundleWatcher[]) add(watcher, watchers, new BundleWatcher[watchers.length + 1]);
}
/**
* Adds a class loading hook to this hook registry.
* @param classLoadingHook a class loading hook object.
*/
public void addClassLoadingHook(ClassLoadingHook classLoadingHook) {
classLoadingHooks = (ClassLoadingHook[]) add(classLoadingHook, classLoadingHooks, new ClassLoadingHook[classLoadingHooks.length + 1]);
}
/**
* Adds a class loading stats hook to this hook registry.
* @param classLoadingStatsHook a class loading hook object.
*/
public void addClassLoadingStatsHook(ClassLoadingStatsHook classLoadingStatsHook) {
classLoadingStatsHooks = (ClassLoadingStatsHook[]) add(classLoadingStatsHook, classLoadingStatsHooks, new ClassLoadingStatsHook[classLoadingStatsHooks.length + 1]);
}
/**
* Adds a class loader delegate hook to this hook registry.
* @param classLoaderDelegateHook a class loader delegate hook.
*/
public void addClassLoaderDelegateHook(ClassLoaderDelegateHook classLoaderDelegateHook) {
classLoaderDelegateHooks = (ClassLoaderDelegateHook[]) add(classLoaderDelegateHook, classLoaderDelegateHooks, new ClassLoaderDelegateHook[classLoaderDelegateHooks.length + 1]);
}
/**
* Adds a storage hook to this hook registry.
* @param storageHook a storage hook object.
*/
public void addStorageHook(StorageHook storageHook) {
storageHooks = (StorageHook[]) add(storageHook, storageHooks, new StorageHook[storageHooks.length + 1]);
}
/**
* Adds a bundle file factory to this hook registry.
* @param factory a bundle file factory object.
*/
public void addBundleFileFactoryHook(BundleFileFactoryHook factory) {
bundleFileFactoryHooks = (BundleFileFactoryHook[]) add(factory, bundleFileFactoryHooks, new BundleFileFactoryHook[bundleFileFactoryHooks.length + 1]);
}
/**
* Adds a bundle file wrapper factory for this hook registry
* @param factory a bundle file wrapper factory object.
*/
public void addBundleFileWrapperFactoryHook(BundleFileWrapperFactoryHook factory) {
bundleFileWrapperFactoryHooks = (BundleFileWrapperFactoryHook[]) add(factory, bundleFileWrapperFactoryHooks, new BundleFileWrapperFactoryHook[bundleFileWrapperFactoryHooks.length + 1]);
}
private Object[] add(Object newValue, Object[] oldValues, Object[] newValues) {
if (readonly)
throw new IllegalStateException("Cannot add hooks dynamically."); //$NON-NLS-1$
if (oldValues.length > 0)
System.arraycopy(oldValues, 0, newValues, 0, oldValues.length);
newValues[oldValues.length] = newValue;
return newValues;
}
/**
* Returns the base adaptor associated with this hook registry.
* @return the base adaptor associated with this hook registry.
*/
public BaseAdaptor getAdaptor() {
return adaptor;
}
}
|