CachingBundleClassLoaderFactory.java :  » J2EE » spring-ide_2.3.0 » org » springframework » osgi » context » internal » classloader » Java Open Source

Java Open Source » J2EE » spring ide_2.3.0 
spring ide_2.3.0 » org » springframework » osgi » context » internal » classloader » CachingBundleClassLoaderFactory.java
/*
 * Copyright 2006-2008 the original author or authors.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      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.springframework.osgi.context.internal.classloader;

import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;

import org.osgi.framework.Bundle;
import org.springframework.osgi.util.BundleDelegatingClassLoader;

/**
 * Default implementation for {@link BundleClassLoaderFactory}.
 * 
 * @author Costin Leau
 * 
 */
class CachingBundleClassLoaderFactory implements BundleClassLoaderFactory {

  private static final String DELIMITER = "|";
  /**
   * bundleToClassLoader cache
   * 
   * since a bundle can be refreshed, the map will return a map of class
   * loaders
   */
  private final Map cache = new WeakHashMap();


  public ClassLoader createClassLoader(Bundle bundle) {
    ClassLoader loader = null;
    // create a bundle identity object
    Object key = createKeyFor(bundle);

    Map loaders = null;
    // get associated class loaders (if any)
    synchronized (cache) {
      loaders = (Map) cache.get(bundle);
      if (loaders == null) {
        loaders = new HashMap(4);
        loader = createBundleClassLoader(bundle);
        loaders.put(key, new WeakReference(loader));
        return loader;
      }
    }
    // check the associated loaders
    synchronized (loaders) {
      WeakReference reference = (WeakReference) loaders.get(key);
      if (reference != null)
        loader = (ClassLoader) reference.get();
      // loader not found (or already recycled)
      if (loader == null) {
        loader = createBundleClassLoader(bundle);
        loaders.put(key, new WeakReference(loader));
      }
      return loader;
    }
  }

  /**
   * Creates a key for the given bundle. This is needed since the bundle can
   * be updated or refreshed and thus can have different class loaders during
   * its lifetime which are not reflected in its identity. Additionally, the
   * given key will behave the same across the OSGi implementations and
   * provide weak reference semantics.
   * 
   * @param bundle OSGi bundle
   * @return key generated for the given bundle
   */
  private Object createKeyFor(Bundle bundle) {
    StringBuffer buffer = new StringBuffer();
    // add the bundle id first
    buffer.append(bundle.getBundleId());
    // followed by its update time (in hex to reduce its length)
    buffer.append(DELIMITER);
    buffer.append(Long.toHexString(bundle.getLastModified()));
    // plus the bundle class name (just to be triple sure)
    buffer.append(DELIMITER);
    buffer.append(bundle.getClass().getName());
    return buffer.toString();
  }

  private ClassLoader createBundleClassLoader(Bundle bundle) {
    return BundleDelegatingClassLoader.createBundleClassLoaderFor(bundle);
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.