001/* This is the preferred <code>ClassLoadingStrategy</code> implementation in a full-blown OSGi-based runtime.
002
003Copyright (c) 2015-2016 The Regents of the University of California; iSencia Belgium NV.
004All rights reserved.
005
006Permission is hereby granted, without written agreement and without
007license or royalty fees, to use, copy, modify, and distribute this
008software and its documentation for any purpose, provided that the above
009copyright notice and the following two paragraphs appear in all copies
010of this software.
011
012IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA LIABLE TO ANY PARTY
013FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
014ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
015THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
016SUCH DAMAGE.
017
018THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
019INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
020MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
021PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
022CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
023ENHANCEMENTS, OR MODIFICATIONS.
024
025PT_COPYRIGHT_VERSION_2
026COPYRIGHTENDKEY
027*/
028
029package org.ptolemy.classloading.osgi;
030
031import java.util.HashSet;
032import java.util.Set;
033
034import org.ptolemy.classloading.ActorOrientedClassProvider;
035import org.ptolemy.classloading.ClassLoadingStrategy;
036import org.ptolemy.classloading.ModelElementClassProvider;
037import org.ptolemy.commons.VersionSpecification;
038
039import ptolemy.kernel.CompositeEntity;
040
041/**
042 * This is the preferred <code>ClassLoadingStrategy</code> implementation in a full-blown OSGi-based runtime.
043 * It supports dynamic actor class updates through OSGi's great dynamism based on micro-services.
044 * <p>
045 * This dynamism is obtained by delegating the class loading to the registered implementations of
046 * <code>ModelElementClassProvider</code> and <code>ActorOrientedClassProvider</code>.
047 * </p>
048 *
049 * @author ErwinDL
050 * @version $Id$
051 * @since Ptolemy II 11.0
052 * @Pt.ProposedRating Yellow (ErwinDL)
053 * @Pt.AcceptedRating Yellow (ErwinDL)
054 */
055public class OSGiClassLoadingStrategy implements ClassLoadingStrategy {
056
057    ///////////////////////////////////////////////////////////////////
058    ////                         public methods                    ////
059
060    /**
061     * Load a Java class.
062     * @param className The namee of the class.
063     * @param versionSpec The version
064     * @return the Class for the given name.
065     * @exception ClassNotFoundException If the class is not found.
066     */
067    @Override
068    public Class<?> loadJavaClass(String className,
069            VersionSpecification versionSpec) throws ClassNotFoundException {
070        Class<?> result = null;
071
072        for (ModelElementClassProvider classProvider : _modelElementClassProviders) {
073            try {
074                result = classProvider.getClass(className, versionSpec);
075                if (result != null) {
076                    break;
077                }
078            } catch (ClassNotFoundException e) {
079                // just means the provider doesn't know about this one
080            }
081        }
082        if (result != null) {
083            return result;
084        } else {
085            throw new ClassNotFoundException(className);
086        }
087    }
088
089    /**
090     *  Load an actor-oriented class, which is typically a .moml file.
091     * @param className The namee of the class.
092     * @param versionSpec The version
093     * @return the Class for the given name.
094     * @exception ClassNotFoundException If the class is not found.
095     */
096    @Override
097    public CompositeEntity loadActorOrientedClass(String className,
098            VersionSpecification versionSpec) throws ClassNotFoundException {
099        CompositeEntity result = null;
100
101        for (ActorOrientedClassProvider classProvider : _actorOrientedClassProviders) {
102            try {
103                result = classProvider.getActorOrientedClass(className,
104                        versionSpec);
105                if (result != null) {
106                    break;
107                }
108            } catch (ClassNotFoundException e) {
109                // just means the provider doesn't know about this one
110            }
111        }
112        if (result != null) {
113            return result;
114        } else {
115            throw new ClassNotFoundException(className);
116        }
117    }
118
119    // provider registration mgmt stuff
120
121    /**
122     * Add the given provider to the set of registered
123     * ModelElementClassProviders.
124     *
125     * @param classProvider should be not-null
126     * @return true if the entry was added successfully
127     * @exception IllegalArgumentException when the given provider is null
128     */
129    public boolean addModelElementClassProvider(
130            ModelElementClassProvider classProvider) {
131        if (classProvider == null) {
132            throw new IllegalArgumentException("classProvider can not be null");
133        }
134        return _modelElementClassProviders.add(classProvider);
135    }
136
137    /**
138     * Remove the given provider from the set of registered
139     * ModelElementClassProviders.
140     *
141     * @param classProvider should be not-null
142     * @return true if the set of registered providers contained the
143     * given instance and it was removed successfully
144     * @exception IllegalArgumentException when the given provider is null
145     */
146    public boolean removeModelElementClassProvider(
147            ModelElementClassProvider classProvider) {
148        if (classProvider == null) {
149            throw new IllegalArgumentException("classProvider can not be null");
150        }
151        return _modelElementClassProviders.remove(classProvider);
152    }
153
154    /**
155     * Clears the set of registered ModelElementClassProviders.
156     * Does not touch the registered ActorOrientedClassProviders.
157     */
158    public void clearModelElementClassProviders() {
159        _modelElementClassProviders.clear();
160    }
161
162    /**
163     * Adds the given provider to the set of registered ActorOrientedClassProviders.
164     *
165     * @param classProvider should be not-null
166     * @return true if the entry was added successfully
167     * @exception IllegalArgumentException when the given provider is null
168     */
169    public boolean addActorOrientedClassProvider(
170            ActorOrientedClassProvider classProvider) {
171        if (classProvider == null) {
172            throw new IllegalArgumentException("classProvider can not be null");
173        }
174        return _actorOrientedClassProviders.add(classProvider);
175    }
176
177    /**
178     * Removes the given provider from the set of registered ActorOrientedClassProviders.
179     *
180     * @param classProvider should be not-null
181     * @return true if the set of registered providers contained the
182     * given instance and it was removed successfully
183     * @exception IllegalArgumentException when the given provider is null
184     */
185    public boolean removeActorOrientedClassProvider(
186            ActorOrientedClassProvider classProvider) {
187        return _actorOrientedClassProviders.remove(classProvider);
188    }
189
190    /**
191     * Clear the set of registered ActorOrientedClassProviders.
192     * Does not touch the registered ModelElementClassProviders.
193     */
194    public void clearActorOrientedClassProviders() {
195        _actorOrientedClassProviders.clear();
196    }
197
198    ///////////////////////////////////////////////////////////////////
199    ////                         private methods                   ////
200
201    /** All registered providers for "plain" model elements like actors, directors, ...*/
202    private Set<ModelElementClassProvider> _modelElementClassProviders = new HashSet<ModelElementClassProvider>();
203    /** All registered providers for actor-oriented classes in a model */
204    private Set<ActorOrientedClassProvider> _actorOrientedClassProviders = new HashSet<ActorOrientedClassProvider>();
205}