/* * Bibliothek - DockingFrames * Library built on Java/Swing, allows the user to "drag and drop" * panels containing any Swing-Component the developer likes to add. * * Copyright (C) 2010 Benjamin Sigg * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Benjamin Sigg * benjamin_sigg@gmx.ch * CH - Switzerland */ package bibliothek.gui.dock.util.extension; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import bibliothek.gui.DockController; /** * Manages a set of {@link Extension}s. * @author Benjamin Sigg */ public class ExtensionManager { /** the controller in whose realm this manager works */ private DockController controller; /** all the extensions of this manager */ private List<Extension> extensions = new ArrayList<Extension>(); /** whether the extensions are installed or not */ private boolean alive = false; /** all shared extensions */ private Map<ExtensionName<?>, Share<?>> shared = new HashMap<ExtensionName<?>, Share<?>>(); /** * Creates a new manager. * @param controller the controller in whose realm this manager works */ public ExtensionManager( DockController controller ){ this.controller = controller; tryLoadDefaultExtensions(); } /** * Tries to load the standard extensions that are developed alongside with the * main-framework. */ protected void tryLoadDefaultExtensions(){ String[] list = { "glass.eclipse.GlassExtension", "bibliothek.gui.ToolbarExtension" }; for( String className : list ){ try { tryLoadExtension( className ); } catch( ClassNotFoundException e ) { // ignore } catch( InstantiationException e ) { e.printStackTrace(); } catch( IllegalAccessException e ) { // ignore } } } private void tryLoadExtension( String className ) throws ClassNotFoundException, InstantiationException, IllegalAccessException{ Class<?> clazz = Class.forName( className ); Object extension = clazz.newInstance(); if( extension instanceof Extension ){ add( (Extension)extension ); } } /** * Adds <code>extension</code> to the list of extensions. * @param extension the new extension */ public void add( Extension extension ){ extensions.add( extension ); if( alive ){ extension.install( controller ); } } /** * Removes <code>extension</code> from the list of extensions. * @param extension the extension to remove */ public void remove( Extension extension ){ if( extensions.remove( extension ) ){ if( alive ){ extension.uninstall( controller ); } } } /** * Gets a list of all extensions that are currently known to this manager. * @return the list of extensions */ public Extension[] getExtensions(){ return extensions.toArray( new Extension[ extensions.size() ] ); } /** * Loads all extensions matching <code>name</code>. * @param <E> the type of extensions that is loaded * @param name the name of the extensions * @return a list containing all non-<code>null</code> extensions, may be empty */ public <E> List<E> load( ExtensionName<E> name ){ List<E> result = new ArrayList<E>(); for( Extension extension : extensions ){ Collection<E> es = extension.load( controller, name ); if( es != null ){ result.addAll( es ); } } return result; } /** * Creates a new {@link SharedExtension} object which uses <code>name</code> as key to read * extensions. The {@link SharedExtension} object can be {@link SharedExtension#bind() bound} * and {@link SharedExtension#unbind() unbound} at any time, it can be reused. * @param name the name of the extension to share * @return the shared extensions */ public <E> SharedExtension<E> share( final ExtensionName<E> name ){ return new SharedExtension<E>(){ private int bound = 0; @SuppressWarnings("unchecked") public void bind(){ if( bound == 0 ){ Share<E> share = (Share<E>)shared.get( name ); if( share == null ){ share = new Share<E>( name ); } share.bind(); } bound++; } @SuppressWarnings("unchecked") public void unbind(){ if( bound == 0 ){ throw new IllegalStateException( "cannot unbind, counter is already 0" ); } bound--; if( bound == 0 ){ Share<E> share = (Share<E>)shared.get( name ); if( share != null ){ share.unbind(); } } } @SuppressWarnings("unchecked") public List<E> get(){ if( bound == 0 ){ throw new IllegalStateException( "SharedExtension is not bound" ); } Share<E> share = (Share<E>)shared.get( name ); return share.get(); } public Iterator<E> iterator(){ return get().iterator(); } public ExtensionName<E> getName(){ return name; } }; } /** * Represents a shared set of extensions. * @author Benjamin Sigg * @param <T> the type of object that is shared */ private class Share<T>{ private int bound = 0; private List<T> extensions; private ExtensionName<T> name; /** * Creates a new cache. * @param name the key of the extensions */ public Share( ExtensionName<T> name ){ this.name = name; } /** * Connects this cache. */ public void bind(){ if( bound == 0 ){ shared.put( name, this ); } bound++; } /** * Disconnects this cache. */ public void unbind(){ bound--; if( bound == 0 ){ shared.remove( name ); } } /** * Gets the content of this cache. * @return the content */ public List<T> get(){ if( extensions == null ){ extensions = Collections.unmodifiableList( load( name ) ); } return extensions; } } /** * Starts up all extensions. */ public void init(){ alive = true; for( Extension extension : extensions ){ extension.install( controller ); } } /** * Stops and removes all extensions. */ public void kill(){ if( alive ){ alive = false; for( Extension extension : extensions ){ extension.uninstall( controller ); } extensions.clear(); } } }