Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
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.aries.blueprint.container;
 
 import java.io.File;
 import java.net.URL;
 import java.util.List;
 
This is the blueprint extender that listens to blueprint bundles.

Version:
$Rev: 1690264 $, $Date: 2015-07-10 16:03:21 +0200 (Fri, 10 Jul 2015) $
 
The QuiesceParticipant implementation class name
 
     private static final String QUIESCE_PARTICIPANT_CLASS = "org.apache.aries.quiesce.participant.QuiesceParticipant";
     private static final Logger LOGGER = LoggerFactory.getLogger(BlueprintExtender.class);
 
     private BundleContext context;
     private final ConcurrentMap<BundleFutureTaskdestroying = new ConcurrentHashMap<BundleFutureTask>();
     private Object bt;
     private volatile boolean stopping;
 
     public void start(BundleContext ctx) {
         .debug("Starting blueprint extender...");
 
         this. = ctx;
         boolean useSystemContext = Boolean.parseBoolean(ctx.getProperty("org.apache.aries.blueprint.use.system.context"));
         BundleContext trackingContext = useSystemContext ? ctx.getBundle(.).getBundleContext() : ctx;
 
          = new NamespaceHandlerRegistryImpl(trackingContext);
          = new ScheduledExecutorServiceWrapper(ctx"Blueprint Extender"new ScheduledExecutorServiceFactory() {
           public ScheduledExecutorService create(String name)
           {
             return Executors.newScheduledThreadPool(3, new BlueprintThreadFactory(name));
           }
         });
         = new BlueprintEventDispatcher(ctx);
        // Ideally we'd want to only track STARTING and ACTIVE bundle, but this is not supported
        // when using equinox composites.  This would ensure that no STOPPING event is lost while
        // tracking the initial bundles. To work around this issue, we need to register
        // a synchronous bundle listener that will ensure the stopping event will be correctly
        // handled.
        .addBundleListener(this);
        int mask = . | . | . | . | .;
         = useSystemContext ? new BundleTracker(trackingContextmaskthis) : new  RecursiveBundleTracker(ctxmaskthis);
        
         = new SingleServiceTracker<ProxyManager>(ctxProxyManager.classnew SingleServiceListener() {
          public void serviceFound() {
            .debug("Found ProxyManager service, starting to process blueprint bundles");
            if ( instanceof BundleTracker) {
            	((BundleTracker).open();
            } else if ( instanceof RecursiveBundleTracker) {
            	((RecursiveBundleTracker).open();
            }
          }
          public void serviceLost() {
            while (!.isEmpty()) {
              for (Bundle bundle : getBundlesToDestroy()) {
                destroyContainer(bundle);
              }
            }
            if ( instanceof BundleTracker) {
            	((BundleTracker).close();
            } else if ( instanceof RecursiveBundleTracker) {
            	((RecursiveBundleTracker).close();
            }
          }
          public void serviceReplaced() {
          }
        });
        .open();
        
        // Determine if the ParserService should ignore unknown namespace handlers
        boolean ignoreUnknownNamespaceHandlers = Boolean.parseBoolean(ctx.getProperty("org.apache.aries.blueprint.parser.service.ignore.unknown.namespace.handlers"));
        // Create and publish a ParserService
         = ctx.registerService(ParserService.class.getName(), 
            new ParserServiceImpl (ignoreUnknownNamespaceHandlers), 
            new Hashtable<StringObject>());
        // Create and publish a BlueprintContainerService
         = ctx.registerService(
                BlueprintExtenderService.class.getName(),
                new BlueprintContainerServiceImpl(),
                new Hashtable<StringObject>());
        try{
            ctx.getBundle().loadClass();
            //Class was loaded, register
              new BlueprintQuiesceParticipant(ctxthis), 
              new Hashtable<StringObject>());
        } 
        catch (ClassNotFoundException e
        {
            .info("No quiesce support is available, so blueprint components will not participate in quiesce operations");
        }
        
        .debug("Blueprint extender started");
    }
    public void stop(BundleContext context) {
        .debug("Stopping blueprint extender...");
         = true;
        AriesFrameworkUtil.safeUnregisterService();
        AriesFrameworkUtil.safeUnregisterService();
        AriesFrameworkUtil.safeUnregisterService();
        // Orderly shutdown of containers
        while (!.isEmpty()) {
            for (Bundle bundle : getBundlesToDestroy()) {
                destroyContainer(bundle);
            }
        }
        if ( instanceof BundleTracker) {
        	((BundleTracker).close();
        } else if ( instanceof RecursiveBundleTracker) {
        	((RecursiveBundleTracker).close();
        }
        .close();
        this..destroy();
        this..destroy();
        .shutdown();
        .debug("Blueprint extender stopped");
    }
    /*
     * SynchronousBundleListener
     */
    public void bundleChanged(BundleEvent event) {
        Bundle bundle = event.getBundle();
        if (bundle.getState() != . && bundle.getState() != .) {
            // The bundle is not in STARTING or ACTIVE state anymore
            // so destroy the context.  Ignore our own bundle since it
            // needs to kick the orderly shutdown and not unregister the namespaces.
            if (bundle != this..getBundle()) {
                destroyContainer(bundle);
            }
        }
    }
    /*
     * BundleTrackerCustomizer
     */
    public Object addingBundle(Bundle bundleBundleEvent event) {
        modifiedBundle(bundleeventbundle);
        return bundle;
    }
    public void modifiedBundle(Bundle bundleBundleEvent eventObject object) {
        // If the bundle being stopped is the system bundle,
        // do an orderly shutdown of all blueprint contexts now
        // so that service usage can actually be useful
        if (.getBundle(0).equals(bundle) && bundle.getState() == .) {
            String val = .getProperty("org.apache.aries.blueprint.preemptiveShutdown");
            if (val == null || Boolean.parseBoolean(val)) {
                stop();
                return;
            }
        }
        if (bundle.getState() != . && bundle.getState() != .) {
            // The bundle is not in STARTING or ACTIVE state anymore
            // so destroy the context.  Ignore our own bundle since it
            // needs to kick the orderly shutdown and not unregister the namespaces.
            if (bundle != this..getBundle()) {
                destroyContainer(bundle);
            }
            return;
        }
        // Do not track bundles given we are stopping
        if () {
            return;
        }
        // For starting bundles, ensure, it's a lazy activation,
        // else we'll wait for the bundle to become ACTIVE
        if (bundle.getState() == .) {
            String activationPolicyHeader = (Stringbundle.getHeaders().get(.);
            if (activationPolicyHeader == null || !activationPolicyHeader.startsWith(.)) {
                // Do not track this bundle yet
                return;
            }
        }
        createContainer(bundle);
    }
    public void removedBundle(Bundle bundleBundleEvent eventObject object) {
        // Nothing to do
        destroyContainer(bundle);
    }
    private boolean createContainer(Bundle bundle) {
        List<Objectpaths = getBlueprintPaths(bundle);
        return createContainer(bundlepaths);
    }
    private boolean createContainer(Bundle bundleList<Objectpaths) {
    try {
            if (paths == null || paths.isEmpty()) {
                // This bundle is not a blueprint bundle, so ignore it
                return false;
            }
            ProxyManager pm = .getService();
            if (pm == null) {
                // The pm isn't available.  It may be because it is being untracked
                return false;
            }
            BundleContext bundleContext = bundle.getBundleContext();
            if (bundleContext == null) {
                // The bundle has been stopped in the mean time
                return false;
            }
            BlueprintContainerImpl blueprintContainer = new BlueprintContainerImpl(bundlebundleContext,
                                                                .getBundle(), ,
                                                                getExecutorService(bundle),
                                                                pathspm);
            synchronized () {
                if (.putIfAbsent(bundleblueprintContainer) != null) {
                    return false;
                }
            }
            String val = .getProperty("org.apache.aries.blueprint.synchronous");
            if (Boolean.parseBoolean(val)) {
                .debug("Starting creation of blueprint bundle {}/{} synchronously"bundle.getSymbolicName(), bundle.getVersion());
                blueprintContainer.run();
            } else {
                .debug("Scheduling creation of blueprint bundle {}/{} asynchronously"bundle.getSymbolicName(), bundle.getVersion());
                blueprintContainer.schedule();
            }
            return true;
        } catch (Throwable t) {
            .warn("Error while creating blueprint container for bundle {}/{}"bundle.getSymbolicName(), bundle.getVersion(), t);
            return false;
        }
    }
    private void destroyContainer(final Bundle bundle) {
        FutureTask future;
        synchronized () {
            .debug("Starting BlueprintContainer destruction process for bundle {}/{}"bundle.getSymbolicName(), bundle.getVersion());
            future = .get(bundle);
            if (future == null) {
                final BlueprintContainerImpl blueprintContainer = .remove(bundle);
                if (blueprintContainer != null) {
                    .debug("Scheduling BlueprintContainer destruction for {}/{}."bundle.getSymbolicName(), bundle.getVersion());
                    future = new FutureTask<Void>(new Runnable() {
                        public void run() {
                            .info("Destroying BlueprintContainer for bundle {}/{}"bundle.getSymbolicName(), bundle.getVersion());
                            try {
                                blueprintContainer.destroy();
                            } finally {
                                .debug("Finished destroying BlueprintContainer for bundle {}/{}"bundle.getSymbolicName(), bundle.getVersion());
                                .removeBlueprintBundle(bundle);
                                synchronized () {
                                    .remove(bundle);
                                }
                            }
                        }
                    }, null);
                    .put(bundlefuture);
                } else {
                    .debug("Not a blueprint bundle or destruction of BlueprintContainer already finished for {}/{}."bundle.getSymbolicName(), bundle.getVersion());
                }
            } else {
                .debug("Destruction already scheduled for {}/{}."bundle.getSymbolicName(), bundle.getVersion());
            }
        }
        if (future != null) {
            try {
                .debug("Waiting for BlueprintContainer destruction for {}/{}."bundle.getSymbolicName(), bundle.getVersion());
                future.run();
                future.get();
            } catch (Throwable t) {
                .warn("Error while destroying blueprint container for bundle {}/{}"bundle.getSymbolicName(), bundle.getVersion(), t);
            }
        }
    }
    private List<ObjectgetBlueprintPaths(Bundle bundle) {
        .debug("Scanning bundle {}/{} for blueprint application"bundle.getSymbolicName(), bundle.getVersion());
        try {
            List<ObjectpathList = new ArrayList<Object>();
            String blueprintHeader = (Stringbundle.getHeaders().get(.);
            String blueprintHeaderAnnotation = (Stringbundle.getHeaders().get(.);
            if (blueprintHeader == null) {
                blueprintHeader = "OSGI-INF/blueprint/";
            }
            List<PathElementpaths = HeaderParser.parseHeader(blueprintHeader);
            for (PathElement path : paths) {
                String name = path.getName();
                if (name.endsWith("/")) {
                    addEntries(bundlename"*.xml"pathList);
                } else {
                    String baseName;
                    String filePattern;
                    int pos = name.lastIndexOf('/');
                    if (pos < 0) {
                        baseName = "/";
                        filePattern = name;
                    } else {
                        baseName = name.substring(0, pos + 1);
                        filePattern = name.substring(pos + 1);
                    }
                    if (hasWildcards(filePattern)) {
                        addEntries(bundlebaseNamefilePatternpathList);
                    } else {
                        addEntry(bundlenamepathList);
                    }
                }
            }
            // Check annotations
            if (blueprintHeaderAnnotation != null && blueprintHeaderAnnotation.trim().equalsIgnoreCase("true")) {
                .debug("Scanning bundle {}/{} for blueprint annotations"bundle.getSymbolicName(), bundle.getVersion());
                ServiceReference sr = this..getServiceReference(BlueprintAnnotationScanner.class.getName());
                if (sr != null) {
                    BlueprintAnnotationScanner bas = (BlueprintAnnotationScannerthis..getService(sr);
                    try {
                        // try to generate the blueprint definition XML
                        URL url = bas.createBlueprintModel(bundle);
                        if (url != null) {
                            pathList.add(url);
                        }
                    } finally {
                        this..ungetService(sr);
                    }
                }
            }
            if (!pathList.isEmpty()) {
                .debug("Found blueprint application in bundle {}/{} with paths: {}"bundle.getSymbolicName(), bundle.getVersion(), pathList);
                // Check compatibility
                // TODO: For lazy bundles, the class is either loaded from an imported package or not found, so it should
                // not trigger the activation.  If it does, we need to use something else like package admin or
                // ServiceReference, or just not do this check, which could be quite harmful.
                if (isCompatible(bundle)) {
                    return pathList;
                } else {
                    .info("Bundle {}/{} is not compatible with this blueprint extender"bundle.getSymbolicName(), bundle.getVersion());
                }
            } else {
                .debug("No blueprint application found in bundle {}/{}"bundle.getSymbolicName(), bundle.getVersion());
            }
        } catch (Throwable t) {
            if (!) {
                .warn("Error creating blueprint container for bundle {}/{}"bundle.getSymbolicName(), bundle.getVersion(), t);
                .blueprintEvent(new BlueprintEvent(.bundle.getBundle(), t));
            }
        }
        return null;
    }
    private List<BundlegetBundlesToDestroy() {
        List<BundlebundlesToDestroy = new ArrayList<Bundle>();
        for (Bundle bundle : .keySet()) {
            ServiceReference[] references = bundle.getRegisteredServices();
            int usage = 0;
            if (references != null) {
                for (ServiceReference reference : references) {
                    usage += getServiceUsage(reference);
                }
            }
            .debug("Usage for bundle {}/{} is {}"bundle.getSymbolicName(), bundle.getVersion(), usage);
            if (usage == 0) {
                bundlesToDestroy.add(bundle);
            }
        }
        if (!bundlesToDestroy.isEmpty()) {
            Collections.sort(bundlesToDestroynew Comparator<Bundle>() {
                public int compare(Bundle b1Bundle b2) {
                    return (int) (b2.getLastModified() - b1.getLastModified());
                }
            });
            if (.isDebugEnabled()) {
                .debug("Selected bundles {} for destroy (no services in use)"toString(bundlesToDestroy));
            }
        } else {
            ServiceReference ref = null;
            for (Bundle bundle : .keySet()) {
                ServiceReference[] references = bundle.getRegisteredServices();
                for (ServiceReference reference : references) {
                    if (getServiceUsage(reference) == 0) {
                        continue;
                    }
                    if (ref == null || reference.compareTo(ref) < 0) {
                        .debug("Currently selecting bundle {}/{} for destroy (with reference {})"bundle.getSymbolicName(), bundle.getVersion(), reference);
                        ref = reference;
                    }
                }
            }
            if (ref != null) {
                bundlesToDestroy.add(ref.getBundle());
            }
            if (.isDebugEnabled()) {
                .debug("Selected bundles {} for destroy (lowest ranking service)"toString(bundlesToDestroy));
            }
        }
        return bundlesToDestroy;
    }
    private static String toString(List<Bundlebundles) {
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for (int i = 0; i < bundles.size(); i++) {
            if (i > 0) {
                sb.append(", ");
            }
            sb.append(bundles.get(i).getSymbolicName());
            sb.append("/");
            sb.append(bundles.get(i).getVersion());
        }
        sb.append("]");
        return sb.toString();
    }
    private static int getServiceUsage(ServiceReference ref) {
        Bundle[] usingBundles = ref.getUsingBundles();
        return (usingBundles != null) ? usingBundles.length : 0;
    }
    private ExecutorService getExecutorService(Bundle bundle) {
        if ( != null) {
            return .find(bundle);
        } else {
            return ;
        }
    }
    interface ExecutorServiceFinder {
        public ExecutorService findBundle bundle );
    }
    private boolean isCompatible(Bundle bundle) {
        // Check compatibility
        boolean compatible;
        if (bundle.getState() == .) {
            try {
                Class<?> clazz = bundle.getBundleContext().getBundle().loadClass(BlueprintContainer.class.getName());
                compatible = (clazz == BlueprintContainer.class);
            } catch (ClassNotFoundException e) {
                compatible = true;
            }
        } else {
            // for lazy bundle, we can't load the class, so just assume it's ok
            compatible = true;
        }
        return compatible;
    }
    
    private boolean hasWildcards(String path) {
        return path.indexOf("*") >= 0; 
    }
    
    private String getFilePart(URL url) {
        String path = url.getPath();
        int index = path.lastIndexOf('/');
        return path.substring(index + 1);
    }
    
    private String cachePath(Bundle bundleString filePath)
    {
      return Integer.toHexString(bundle.hashCode()) + "/" + filePath;
    }    
    
    private URL getOverrideURLForCachePath(String privatePath){
        URL override = null;
        File privateDataVersion = .getDataFile(privatePath);
        if (privateDataVersion != null
                && privateDataVersion.exists()) {
            try {
                override = privateDataVersion.toURI().toURL();
            } catch (MalformedURLException e) {
                .error("Unexpected URL Conversion Issue"e);
            }
        }
        return override;
    }
    
    private URL getOverrideURL(Bundle bundleString path){
        String cachePath = cachePath(bundlepath);
        return getOverrideURLForCachePath(cachePath);
    }
    
    private URL getOverrideURL(Bundle bundleURL pathString basePath){
        String cachePath = cachePath(bundlebasePath + getFilePart(path));
        return getOverrideURLForCachePath(cachePath);
    }    
    
    private void addEntry(Bundle bundleString pathList<ObjectpathList) {
        URL override = getOverrideURL(bundlepath);
        if(override == null) {
            pathList.add(path);
        } else {
            pathList.add(override);
        }
    }
    
    private void addEntries(Bundle bundleString pathString filePatternList<ObjectpathList) {
        Enumeration<?> e = bundle.findEntries(pathfilePatternfalse);
        while (e != null && e.hasMoreElements()) {
            URL u = (URLe.nextElement();
            URL override = getOverrideURL(bundleupath);
            if(override == null) {
                pathList.add(u);
            } else {
                pathList.add(override);
            }
        }
    }
    
    {
        return .get(bundle);
    }
    private class BlueprintContainerServiceImpl implements BlueprintExtenderService {
        public BlueprintContainer createContainer(Bundle bundle) {
            if (BlueprintExtender.this.createContainer(bundle)) {
                return getContainer(bundle);
            } else {
                return null;
            }
        }
        public BlueprintContainer createContainer(Bundle bundleList<ObjectblueprintPaths) {
            if (BlueprintExtender.this.createContainer(bundleblueprintPaths)) {
                return getContainer(bundle);
            } else {
                return null;
            }
        }
        public void destroyContainer(Bundle bundleBlueprintContainer container) {
            BlueprintContainer bundleContainer = getContainer(bundle);
            if (bundleContainer != container) {
                String error = "Unexpected Blueprint Container";
                .error(error);
                throw new IllegalArgumentException(error);
            }
            BlueprintExtender.this.destroyContainer(bundle);
        }
        public BlueprintContainer getContainer(Bundle bundle) {
            return BlueprintExtender.this.getBlueprintContainerImpl(bundle);
        }
    }
    
New to GrepCode? Check out our FAQ X