5858 */
5959public class Context implements Disposable {
6060
61+ // -- Constants --
62+
63+ /**
64+ * System property indicating whether the context should fail fast when
65+ * is attempts to instantiate a required service which is invalid or missing.
66+ * If this property is set to "false" then the context creation will attempt
67+ * to continue even when a required service cannot be instantiated. Otherwise,
68+ * the constructor will throw an {@link IllegalArgumentException} in that situation.
69+ */
70+ public static final String STRICT_PROPERTY = "scijava.context.strict" ;
71+
6172 // -- Fields --
6273
6374 /** Index of the application context's services. */
@@ -66,7 +77,11 @@ public class Context implements Disposable {
6677 /** Master index of all plugins known to the application context. */
6778 private final PluginIndex pluginIndex ;
6879
69- /** Creates a new SciJava application context with all available services. */
80+ /**
81+ * Creates a new SciJava application context with all available services.
82+ *
83+ * @see #Context(Collection, PluginIndex, boolean)
84+ */
7085 public Context () {
7186 this (false );
7287 }
@@ -76,6 +91,7 @@ public Context() {
7691 *
7792 * @param empty If true, the context will be empty; otherwise, it will be
7893 * initialized with all available services.
94+ * @see #Context(Collection, PluginIndex, boolean)
7995 */
8096 @ SuppressWarnings ("unchecked" )
8197 public Context (final boolean empty ) {
@@ -102,13 +118,12 @@ public Context(final boolean empty) {
102118 *
103119 * @param serviceClasses A list of types that implement the {@link Service}
104120 * interface (e.g., {@code DisplayService.class}).
121+ * @see #Context(Collection, PluginIndex, boolean)
105122 * @throws ClassCastException If any of the given arguments do not implement
106123 * the {@link Service} interface.
107124 */
108- @ SuppressWarnings ({ "rawtypes" , "unchecked" })
109- public Context (final Class ... serviceClasses ) {
110- this (serviceClasses != null ? (Collection ) Arrays .asList (serviceClasses )
111- : Arrays .asList (Service .class ));
125+ public Context (@ SuppressWarnings ("rawtypes" ) final Class ... serviceClasses ) {
126+ this (serviceClassList (serviceClasses ));
112127 }
113128
114129 /**
@@ -117,34 +132,69 @@ public Context(final Class... serviceClasses) {
117132 *
118133 * @param serviceClasses A collection of types that implement the
119134 * {@link Service} interface (e.g., {@code DisplayService.class}).
135+ * @see #Context(Collection, PluginIndex, boolean)
120136 */
121137 public Context (final Collection <Class <? extends Service >> serviceClasses ) {
122138 this (serviceClasses , null );
123139 }
124140
141+ /**
142+ * Creates a new SciJava application context with the specified services (and
143+ * any required service dependencies).
144+ *
145+ * @param serviceClasses A collection of types that implement the
146+ * {@link Service} interface (e.g., {@code DisplayService.class}).
147+ * @param strict Whether context creation will fail fast when there is
148+ * is an error instantiating a required service.
149+ * @see #Context(Collection, PluginIndex, boolean)
150+ */
151+ public Context (final Collection <Class <? extends Service >> serviceClasses ,
152+ final boolean strict )
153+ {
154+ this (serviceClasses , null , strict );
155+ }
156+
125157 /**
126158 * Creates a new SciJava application with the specified PluginIndex. This
127159 * allows a base set of available plugins to be defined, and is useful when
128- * plugins that would not be returned by the PluginIndex's PluginFinder are
129- * desired.
130- * <p>
131- * NB: the {@link PluginIndex#discover()} method may still be called, adding
132- * additional plugins to this index. The mechanism of discovery should be
133- * configured exclusively through the attached
134- * {@link org.scijava.plugin.PluginFinder}.
135- * </p>
160+ * plugins that would not be returned by the {@link PluginIndex}'s
161+ * {@link org.scijava.plugin.PluginFinder} are desired.
136162 *
137163 * @param pluginIndex The plugin index to use when discovering and indexing
138164 * plugins. If you wish to completely control how services are
139165 * discovered (i.e., use your own
140166 * {@link org.scijava.plugin.PluginFinder} implementation), then you
141- * can pass a custom {@link PluginIndex} here.
167+ * can pass a custom {@link PluginIndex} here. Passing null will
168+ * result in a default plugin index being constructed and used.
169+ * @see #Context(Collection, PluginIndex, boolean)
142170 */
143171 @ SuppressWarnings ("unchecked" )
144172 public Context (final PluginIndex pluginIndex ) {
145173 this (Arrays .<Class <? extends Service >> asList (Service .class ), pluginIndex );
146174 }
147175
176+ /**
177+ * Creates a new SciJava application context with the specified services (and
178+ * any required service dependencies). Service dependency candidates are
179+ * selected from those discovered by the given {@link PluginIndex}'s
180+ * associated {@link org.scijava.plugin.PluginFinder}.
181+ *
182+ * @param serviceClasses A collection of types that implement the
183+ * {@link Service} interface (e.g., {@code DisplayService.class}).
184+ * @param pluginIndex The plugin index to use when discovering and indexing
185+ * plugins. If you wish to completely control how services are
186+ * discovered (i.e., use your own
187+ * {@link org.scijava.plugin.PluginFinder} implementation), then you
188+ * can pass a custom {@link PluginIndex} here. Passing null will
189+ * result in a default plugin index being constructed and used.
190+ * @see #Context(Collection, PluginIndex, boolean)
191+ */
192+ public Context (final Collection <Class <? extends Service >> serviceClasses ,
193+ final PluginIndex pluginIndex )
194+ {
195+ this (serviceClasses , pluginIndex , strict ());
196+ }
197+
148198 /**
149199 * Creates a new SciJava application context with the specified services (and
150200 * any required service dependencies). Service dependency candidates are
@@ -166,17 +216,21 @@ public Context(final PluginIndex pluginIndex) {
166216 * plugins. If you wish to completely control how services are
167217 * discovered (i.e., use your own
168218 * {@link org.scijava.plugin.PluginFinder} implementation), then you
169- * can pass a custom {@link PluginIndex} here.
219+ * can pass a custom {@link PluginIndex} here. Passing null will
220+ * result in a default plugin index being constructed and used.
221+ * @param strict Whether context creation will fail fast when there is
222+ * is an error instantiating a required service.
170223 */
171224 public Context (final Collection <Class <? extends Service >> serviceClasses ,
172- final PluginIndex pluginIndex )
225+ final PluginIndex pluginIndex , final boolean strict )
173226 {
174227 serviceIndex = new ServiceIndex ();
175228
176229 this .pluginIndex = pluginIndex == null ? new PluginIndex () : pluginIndex ;
177230 this .pluginIndex .discover ();
178231
179- final ServiceHelper serviceHelper = new ServiceHelper (this , serviceClasses );
232+ final ServiceHelper serviceHelper =
233+ new ServiceHelper (this , serviceClasses , strict );
180234 serviceHelper .loadServices ();
181235 }
182236
@@ -323,6 +377,20 @@ public void dispose() {
323377 }
324378 }
325379
380+ // -- Utility methods --
381+
382+ /**
383+ * Utility method for converting a varargs list of service classes to a
384+ * {@link List} of those classes.
385+ */
386+ @ SuppressWarnings ({ "rawtypes" , "unchecked" })
387+ public static List <Class <? extends Service >> serviceClassList (
388+ final Class ... serviceClasses )
389+ {
390+ return serviceClasses != null ? (List ) Arrays .asList (serviceClasses )
391+ : Arrays .asList (Service .class );
392+ }
393+
326394 // -- Helper methods --
327395
328396 private String createMissingServiceMessage (
@@ -357,4 +425,8 @@ private String createMissingServiceMessage(
357425 return msg .toString ();
358426 }
359427
428+ private static boolean strict () {
429+ return !"false" .equals (System .getProperty (STRICT_PROPERTY ));
430+ }
431+
360432}
0 commit comments