Implement DynamicSet<T>, DynamicMap<T> to provide bindings in Guice
The core server can now declare that it needs a DynamicSet supplied by
Guice at runtime:
  DynamicSet.setOf(binder(), SomeBaseType.class);
and then receive this as an injection:
  DynamicSet<SomeBaseType> theThings
Core server code can register static implementations into this set:
  DynamicSet.bind(binder(), SomeBaseType.class).to(AnImpl.class);
Plugins may use the same syntax in their own Guice modules to register
their own implementations. When a plugin starts, its registrations
will be added to the DynamicSet, and when it stops, the references get
cleaned up automatically. During a hot reload of a plugin references
from the old plugin and the new plugin are matched up by collection
member type and Guice annotation information, and atomically swapped.
Plugins can use automatic registration if interfaces are annotated
with @ExtensionPoint and the plugin implementation is annoated with
@Listen and also implements the interface, directly or indirectly
through its base classes or interfaces:
  (gerrit-extension-api)
  @ExtensionPoint
  public interface NewChangeListener {
  (gerrit-server)
  DynamicSet.setOf(binder(), NewChangeListener.class);
  (plugin or extension code)
  @Listen
  class OnNewChange implements NewChangeListener {
Automatic registration binds the listeners into the system module,
which may prevent plugins or extensions from automatically connecting
with extension points inside of the HTTP or SSH servers. This
shouldn't generally be a problem as the majority of interfaces plugins
or extensions care about will be defined in the core server, and thus
be in the system module.
Change-Id: Ic8f371d97f8f0ddb6cad97fef3b58e1c3d32381f
			
			
This commit is contained in:
		@@ -0,0 +1,41 @@
 | 
			
		||||
// Copyright (C) 2012 The Android Open Source Project
 | 
			
		||||
//
 | 
			
		||||
// 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 com.google.gerrit.extensions.annotations;
 | 
			
		||||
 | 
			
		||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
 | 
			
		||||
 | 
			
		||||
import com.google.gerrit.extensions.registration.DynamicSet;
 | 
			
		||||
import com.google.inject.BindingAnnotation;
 | 
			
		||||
 | 
			
		||||
import java.lang.annotation.ElementType;
 | 
			
		||||
import java.lang.annotation.Retention;
 | 
			
		||||
import java.lang.annotation.Target;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Annotation for interfaces that accept auto-registered implementations.
 | 
			
		||||
 * <p>
 | 
			
		||||
 * Interfaces that accept automatically registered implementations into their
 | 
			
		||||
 * {@link DynamicSet} must be tagged with this annotation.
 | 
			
		||||
 * <p>
 | 
			
		||||
 * Plugins or extensions that implement an {@code @ExtensionPoint} interface
 | 
			
		||||
 * should use the {@link Listen} annotation to automatically register.
 | 
			
		||||
 *
 | 
			
		||||
 * @see Listen
 | 
			
		||||
 */
 | 
			
		||||
@Target({ElementType.TYPE})
 | 
			
		||||
@Retention(RUNTIME)
 | 
			
		||||
@BindingAnnotation
 | 
			
		||||
public @interface ExtensionPoint {
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,39 @@
 | 
			
		||||
// Copyright (C) 2012 The Android Open Source Project
 | 
			
		||||
//
 | 
			
		||||
// 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 com.google.gerrit.extensions.annotations;
 | 
			
		||||
 | 
			
		||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
 | 
			
		||||
 | 
			
		||||
import com.google.inject.BindingAnnotation;
 | 
			
		||||
 | 
			
		||||
import java.lang.annotation.ElementType;
 | 
			
		||||
import java.lang.annotation.Retention;
 | 
			
		||||
import java.lang.annotation.Target;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Annotation for auto-registered extension point implementations.
 | 
			
		||||
 * <p>
 | 
			
		||||
 * Plugins or extensions using auto-registration should apply this annotation to
 | 
			
		||||
 * any non-abstract class that implements an unnamed extension point, such as a
 | 
			
		||||
 * notification listener. Gerrit will automatically determine which extension
 | 
			
		||||
 * points to apply based on the interfaces the type implements.
 | 
			
		||||
 *
 | 
			
		||||
 * @see Export
 | 
			
		||||
 */
 | 
			
		||||
@Target({ElementType.TYPE})
 | 
			
		||||
@Retention(RUNTIME)
 | 
			
		||||
@BindingAnnotation
 | 
			
		||||
public @interface Listen {
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user