You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by zo...@apache.org on 2011/02/27 22:05:20 UTC
svn commit: r1075147 [9/23] - in /aries/tags/blueprint-0.3: ./
blueprint-annotation-api/ blueprint-annotation-api/src/
blueprint-annotation-api/src/main/ blueprint-annotation-api/src/main/java/
blueprint-annotation-api/src/main/java/org/ blueprint-anno...
Added: aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/BeanProcessor.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/BeanProcessor.java?rev=1075147&view=auto
==============================================================================
--- aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/BeanProcessor.java (added)
+++ aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/BeanProcessor.java Sun Feb 27 21:05:07 2011
@@ -0,0 +1,57 @@
+/**
+ * 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;
+
+import org.osgi.service.blueprint.reflect.BeanMetadata;
+
+/**
+ * TODO: javadoc
+ *
+ * Processors must be advertized as being such. This can be done by using
+ * the custom attribtue defined in the extension schema.
+ * <pre>
+ * <bp:bean ext:role="processor" ...>
+ * </pre>
+ *
+ * @version $Rev: 896324 $, $Date: 2010-01-06 06:05:04 +0000 (Wed, 06 Jan 2010) $
+ */
+public interface BeanProcessor extends Processor {
+
+ /**
+ * Interface from which a BeanProcessor can obtain another bean.
+ */
+ interface BeanCreator {
+ /**
+ * Obtains a new instance of the Bean this BeanProcessor handled. <br>
+ * New instances have been processed by the same chain of BeanProcessors
+ * that the original Bean had been.
+ * @return new instance of bean.
+ */
+ Object getBean();
+ }
+
+ Object beforeInit(Object bean, String beanName, BeanCreator beanCreator, BeanMetadata beanData);
+
+ Object afterInit(Object bean, String beanName, BeanCreator beanCreator, BeanMetadata beanData);
+
+ void beforeDestroy(Object bean, String beanName);
+
+ void afterDestroy(Object bean, String beanName);
+
+}
Added: aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/BlueprintConstants.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/BlueprintConstants.java?rev=1075147&view=auto
==============================================================================
--- aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/BlueprintConstants.java (added)
+++ aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/BlueprintConstants.java Sun Feb 27 21:05:07 2011
@@ -0,0 +1,40 @@
+/**
+ * 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;
+
+public interface BlueprintConstants {
+
+ public static final String BUNDLE_BLUEPRINT_HEADER = "Bundle-Blueprint";
+
+ public static final String BUNDLE_BLUEPRINT_ANNOTATION_HEADER = "Bundle-Blueprint-Annotation";
+
+ public static final String TIMEOUT_DIRECTIVE = "blueprint.timeout";
+
+ public static final String GRACE_PERIOD = "blueprint.graceperiod";
+
+ public static final String BUNDLE_VERSION = "bundle.version";
+
+ public static final String COMPONENT_NAME_PROPERTY = "osgi.service.blueprint.compname";
+
+ public static final String CONTAINER_SYMBOLIC_NAME_PROPERTY = "osgi.blueprint.container.symbolicname";
+
+ public static final String CONTAINER_VERSION_PROPERTY = "osgi.blueprint.container.version";
+
+ public static final String XML_VALIDATION = "blueprint.aries.xml-validation";
+}
Added: aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ComponentDefinitionRegistry.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ComponentDefinitionRegistry.java?rev=1075147&view=auto
==============================================================================
--- aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ComponentDefinitionRegistry.java (added)
+++ aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ComponentDefinitionRegistry.java Sun Feb 27 21:05:07 2011
@@ -0,0 +1,106 @@
+/**
+ * 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;
+
+import java.util.List;
+import java.util.Set;
+
+import org.osgi.service.blueprint.reflect.ComponentMetadata;
+import org.osgi.service.blueprint.reflect.Target;
+
+public interface ComponentDefinitionRegistry {
+
+ /**
+ * Determine if the component registry contains a component definition for the given id
+ * @param id
+ * @return
+ */
+ boolean containsComponentDefinition(String id);
+
+ /**
+ * Retrieve a component's metadata by id
+ * @param id The id of the component. This is either the id specified in the Blueprint xml or the
+ * generated id of an unnamed component
+ * @return the <code>ComponentMetadata</code> or <code>null</code> if the id does not match
+ * any registered component
+ */
+ ComponentMetadata getComponentDefinition(String id);
+
+ /**
+ * Returns a set of the id of top-level blueprint components (both named and unnamed).
+ *
+ * The ids of unnamed components are Blueprint generated. Anonymous components, which have no
+ * id, are not part of the set.
+ * @return
+ */
+ Set<String> getComponentDefinitionNames();
+
+ /**
+ * Register a new component
+ *
+ * The <code>ComponentMetadata</code> argument must have an id. So unnamed components should have an id
+ * generated prior to invoking this method. Also, no component definition may already be registered
+ * under the same id.
+ *
+ * @param component the component to be registered
+ * @throws IllegalArgumentException if the component has no id
+ * @throws ComponentNameAlreadyInUseException if there already exists a component definition
+ * in the registry with the same id
+ */
+ void registerComponentDefinition(ComponentMetadata component);
+
+ /**
+ * Remove the component definition with a given id
+ *
+ * If no component is registered under the id, this method is a no-op.
+ * @param id the id of the component definition to be removed
+ */
+ void removeComponentDefinition(String id);
+
+ void registerTypeConverter(Target component);
+
+ List<Target> getTypeConverters();
+
+ /**
+ * Register an interceptor for a given component
+ *
+ * Since the interceptor is registered against a <code>ComponentMetadata</code> instance and not an id,
+ * interceptors can be registered for anonymous components as well as named and unnamed components.
+ *
+ * Note: Although an interceptor is registered against a specific <code>ComponentMetadata</code> instance,
+ * an interceptor should not rely on this fact. This will allow <code>NamespaceHandlers</code> and
+ * <code>ComponentDefinitionRegistryProcessors</code> to respect registered interceptors even when
+ * the actual <code>ComponentMetadata</code> instance is changed or augmented. If an interceptor does
+ * not support such a scenario it should nevertheless fail gracefully in the case of modified
+ * <code>ComponentMetadata</code> instances.
+ *
+ * Note: at the time of this writing (version 0.1) interceptors are only supported for <code>BeanMetadata</code>.
+ * Interceptors registered against other component types will be ignored.
+ *
+ * @param component the component the interceptor is to be registered against
+ * @param interceptor the interceptor to be used
+ */
+ void registerInterceptorWithComponent(ComponentMetadata component, Interceptor interceptor);
+
+ /**
+ * Retrieve all interceptors registered against a <code>ComponentMetadata</code> instance
+ * @param component
+ * @return a list of interceptors sorted by decreasing rank. The list may be empty if no interceptors have been defined
+ */
+ List<Interceptor> getInterceptors(ComponentMetadata component);
+
+}
Added: aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ComponentDefinitionRegistryProcessor.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ComponentDefinitionRegistryProcessor.java?rev=1075147&view=auto
==============================================================================
--- aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ComponentDefinitionRegistryProcessor.java (added)
+++ aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ComponentDefinitionRegistryProcessor.java Sun Feb 27 21:05:07 2011
@@ -0,0 +1,48 @@
+/**
+ * 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;
+
+/**
+ * A processor that processes Blueprint component definitions after they have been parsed but before
+ * component managers are created.
+ *
+ * Component definition registry processors must be advertised as such in the blueprint xml. Do this by using
+ * the custom attribute defined in the extension schema.
+ * <pre>
+ * <bp:bean ext:role="processor" ...>
+ * </pre>
+ *
+ * When a definition registry processor is invoked type converters and registry processors have been already
+ * been created. Hence, changing component definitions for these or any components referenced by them will have
+ * no effect.
+ *
+ * Note: a processor that replaces existing component definitions with new ones should take care to copy
+ * interceptors defined against the old component definition if appropriate
+ *
+ * @version $Rev: 922829 $, $Date: 2010-03-14 12:34:19 +0000 (Sun, 14 Mar 2010) $
+ */
+public interface ComponentDefinitionRegistryProcessor {
+
+ /**
+ * Process a <code>ComponentDefinitionRegistry</code>
+ * @param registry
+ */
+ public void process(ComponentDefinitionRegistry registry);
+
+}
Added: aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ComponentNameAlreadyInUseException.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ComponentNameAlreadyInUseException.java?rev=1075147&view=auto
==============================================================================
--- aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ComponentNameAlreadyInUseException.java (added)
+++ aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ComponentNameAlreadyInUseException.java Sun Feb 27 21:05:07 2011
@@ -0,0 +1,33 @@
+/**
+ * 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;
+
+
+public class ComponentNameAlreadyInUseException extends RuntimeException {
+ private String conflictingName;
+
+ public ComponentNameAlreadyInUseException(String conflictingName) {
+ this.conflictingName = conflictingName;
+ }
+
+ public String getMessage() {
+ return "Name '" + this.conflictingName + "' is already in use by a registered component";
+ }
+
+ public String getConflictingName() {
+ return this.conflictingName;
+ }}
Added: aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ExtendedBeanMetadata.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ExtendedBeanMetadata.java?rev=1075147&view=auto
==============================================================================
--- aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ExtendedBeanMetadata.java (added)
+++ aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ExtendedBeanMetadata.java Sun Feb 27 21:05:07 2011
@@ -0,0 +1,50 @@
+/**
+ * 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;
+
+import org.osgi.service.blueprint.reflect.BeanMetadata;
+
+/**
+ * An extended <code>BeanMetadata</code> that allows specifying if
+ * the bean instances are processors or not.
+ *
+ * Such processors have to be instantiated before instantiating all
+ * other singletons, but to avoid breaking the lazy activation of
+ * bundles, the Blueprint container needs to be aware of those and not
+ * try to load the class to perform some introspection.
+ */
+public interface ExtendedBeanMetadata extends BeanMetadata {
+
+ boolean isProcessor();
+
+ /**
+ * Provide an actual class, this overrides the class name if set. This is
+ * useful for Namespace Handler services that do not want to force the
+ * Blueprint bundle to import implementation classes.
+ *
+ * @return Return the class to use in runtime or <code>null</code>.
+ */
+
+ Class<?> getRuntimeClass();
+
+ /**
+ * Whether the bean allows properties to be injected directly into its fields in the case
+ * where an appropriate setter method is not available.
+ * @return Whether field injection is allowed
+ */
+ boolean getFieldInjection();
+}
Added: aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ExtendedBlueprintContainer.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ExtendedBlueprintContainer.java?rev=1075147&view=auto
==============================================================================
--- aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ExtendedBlueprintContainer.java (added)
+++ aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ExtendedBlueprintContainer.java Sun Feb 27 21:05:07 2011
@@ -0,0 +1,64 @@
+/**
+ * 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;
+
+import java.security.AccessControlContext;
+import java.util.Dictionary;
+import java.util.List;
+
+import org.apache.aries.blueprint.container.ServiceRecipe;
+import org.apache.aries.blueprint.di.Repository;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.blueprint.container.BlueprintContainer;
+import org.osgi.service.blueprint.container.BlueprintListener;
+import org.osgi.service.blueprint.container.Converter;
+
+/**
+ * TODO: javadoc
+ *
+ * @version $Rev: 1002318 $, $Date: 2010-09-28 19:47:49 +0100 (Tue, 28 Sep 2010) $
+ */
+public interface ExtendedBlueprintContainer extends BlueprintContainer {
+
+ BundleContext getBundleContext();
+
+ Bundle getExtenderBundle();
+
+ BlueprintListener getEventDispatcher();
+
+ Converter getConverter();
+
+ Class loadClass(String name) throws ClassNotFoundException;
+
+ ComponentDefinitionRegistry getComponentDefinitionRegistry();
+
+ <T extends Processor> List<T> getProcessors(Class<T> type);
+
+ Repository getRepository();
+
+ ServiceRegistration registerService(String[] classes, Object service, Dictionary properties);
+
+ Object getService(ServiceReference reference);
+
+ AccessControlContext getAccessControlContext();
+
+ void reload();
+
+}
Added: aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ExtendedReferenceListMetadata.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ExtendedReferenceListMetadata.java?rev=1075147&view=auto
==============================================================================
--- aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ExtendedReferenceListMetadata.java (added)
+++ aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ExtendedReferenceListMetadata.java Sun Feb 27 21:05:07 2011
@@ -0,0 +1,30 @@
+/**
+ * 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;
+
+import org.osgi.service.blueprint.reflect.ReferenceListMetadata;
+
+/**
+ * TODO: javadoc
+ *
+ * @version $Rev: 896324 $, $Date: 2010-01-06 06:05:04 +0000 (Wed, 06 Jan 2010) $
+ */
+public interface ExtendedReferenceListMetadata extends ReferenceListMetadata, ExtendedServiceReferenceMetadata {
+
+ int PROXY_METHOD_GREEDY = 2;
+
+}
Added: aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ExtendedServiceReferenceMetadata.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ExtendedServiceReferenceMetadata.java?rev=1075147&view=auto
==============================================================================
--- aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ExtendedServiceReferenceMetadata.java (added)
+++ aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ExtendedServiceReferenceMetadata.java Sun Feb 27 21:05:07 2011
@@ -0,0 +1,36 @@
+/**
+ * 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;
+
+import org.osgi.service.blueprint.reflect.ServiceReferenceMetadata;
+
+/**
+ * TODO: javadoc
+ *
+ * @version $Rev: 950985 $, $Date: 2010-06-03 14:19:22 +0100 (Thu, 03 Jun 2010) $
+ */
+public interface ExtendedServiceReferenceMetadata extends ServiceReferenceMetadata {
+
+ int PROXY_METHOD_DEFAULT = 0;
+
+ int PROXY_METHOD_CLASSES = 1;
+
+ int getProxyMethod();
+
+ Class getRuntimeInterface();
+
+}
Added: aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/Interceptor.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/Interceptor.java?rev=1075147&view=auto
==============================================================================
--- aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/Interceptor.java (added)
+++ aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/Interceptor.java Sun Feb 27 21:05:07 2011
@@ -0,0 +1,68 @@
+/*
+ * 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;
+
+import java.lang.reflect.Method;
+
+import org.osgi.service.blueprint.reflect.ComponentMetadata;
+
+/**
+ * An Interceptor interface provides support for custom interceptor implementation.
+ */
+public interface Interceptor {
+ /**
+ * This is called just before the method m is invocation.
+ * @param cm : the component's metada
+ * @param m: the method to be invoked
+ * @param parameters: method parameters
+ * @return token which will subsequently be passed to postCall
+ * @throws Throwable
+ */
+ public Object preCall(ComponentMetadata cm, Method m, Object... parameters) throws Throwable;
+
+ /**
+ * This method is called after the method m is invoked and returned normally.
+ * @param cm: the component metadata
+ * @param m: the method invoked
+ * @param returnType : the return object
+ * @param preCallToken token returned by preCall
+ * @throws Throwable
+ */
+ public void postCallWithReturn(ComponentMetadata cm, Method m, Object returnType, Object preCallToken) throws Throwable;
+
+ /**
+ * The method is called after the method m is invoked and causes an exception.
+ * @param cm : the component metadata
+ * @param m : the method invoked
+ * @param ex : the <code>Throwable</code> thrown
+ * @param preCallToken token returned by preCall
+ * @throws Throwable
+ */
+ public void postCallWithException(ComponentMetadata cm, Method m, Throwable ex, Object preCallToken) throws Throwable;
+
+
+ /**
+ * Return the rank of the interceptor, which is used to determine the order of the interceptors to be invoked
+ * Rank is between Integer.MIN_VALUE and Integer.MAX_VALUE, interceptors are called in the order of highest value
+ * rank first to lowest value rank last i.e. an interceptor with rank Integer.MAX_VALUE will be called before
+ * all others (except of the same rank).
+ * @return the rank of the interceptor
+ */
+ public int getRank();
+}
Added: aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/NamespaceHandler.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/NamespaceHandler.java?rev=1075147&view=auto
==============================================================================
--- aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/NamespaceHandler.java (added)
+++ aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/NamespaceHandler.java Sun Feb 27 21:05:07 2011
@@ -0,0 +1,121 @@
+/**
+ * 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;
+
+import java.net.URL;
+import java.util.Set;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import org.osgi.service.blueprint.reflect.ComponentMetadata;
+import org.osgi.service.blueprint.reflect.Metadata;
+
+/**
+ * A processor for custom blueprint extensions
+ *
+ * Namespace handlers must be registered in the OSGi service registry with the
+ * <code>osgi.service.blueprint.namespace</code> service property denoting the namespace URIs this
+ * handler can process. The service property value can be either a single <code>String</code> or <code>URI</code>,
+ * or a <code>Collection</code> respectively array of <code>String</code> or <code>URI</code>.
+ *
+ * During parsing when the blueprint extender encounters an element from a non-blueprint namespace it will search
+ * for a namespace handler for the namespace that is compatible with blueprint bundle being processed. Then
+ * for a stand-alone component the parser will invoke the <code>parse</code> method
+ * to create the <code>Metadata</code> for the xml element while for an element that is part
+ * of an existing component the parser will invoke the <code>decorated</code> method to augment
+ * the enclosing <code>ComponentMetadata</code> instance. Various utilities to interact with
+ * the blueprint parser are available to a namespace handler via the <code>ParserContext</code> argument
+ * passed to <code>parse</code> and <code>decorate</code>.
+ *
+ * Recommended behaviour:
+ * <ul>
+ * <li>New metadata objects should be created via calling <code>ParserContext.createMetadata(..)</code> and
+ * casting the returned object to the appropriate <code>MutableComponentMetadata</code> interface.
+ * This method ensures that the metadata object implements the interfaces necessary for other namespace handlers
+ * to be able to use the metadata object.<br/>
+ * Also, to prevent id clashes, component ids should be generated by calling <code>ParserContext.generateId()</code>.
+ * </li>
+ * <li>A namespace handler should not return new metadata instances from the <code>decorate</code> method if
+ * the same result could also be achieved by operating on a <code>MutableComponentMetadata</code> instance.
+ * </li>
+ * <li>A namespace handler should not assume the existence of predefined entries in the component definition
+ * registry such as <code>blueprintBundle</code> or <code>blueprintBundleContext</code>. In the case of a dry
+ * parse (i.e. a parse of the blueprint xml files without a backing OSGi bundle), these values will not be
+ * available
+ * </li>
+ * </ul>
+ */
+public interface NamespaceHandler {
+ /**
+ * Retrieve a URL from where the schema for a given namespace can be retrieved
+ * @param namespace The schema's namespace
+ * @return A URL that points to the location of the schema or null if the namespace validation
+ * is not needed
+ */
+ URL getSchemaLocation(String namespace);
+
+ /**
+ * Specify a set of classes that must be consistent between a blueprint bundle and this namespace handler
+ *
+ * The blueprint extender will not invoke a namespace handler if any of the managed classes are inconsistent
+ * with the class space of the blueprint bundle (i.e. if the blueprint bundle loads any of the managed classes
+ * from a different classloader).
+ *
+ * @return a <code>Set</code> of classes that must be compatible with any blueprint bundle for which this namespace
+ * handler is to apply or <code>null</code> if no compatibility checks are to be performed
+ */
+ Set<Class> getManagedClasses();
+
+ /**
+ * Parse a stand-alone blueprint component
+ *
+ * Given an <code>Element</code> node as a root, this method parses the stand-alone component and returns its
+ * metadata. The supplied <code>ParserContext</code> should be used to parse embedded blueprint elements as well
+ * as creating metadata.
+ *
+ * @param element The DOM element representing the custom component
+ * @param context The <code>ParserContext</code> for parsing sub-components and creating metadata objects
+ * @return A metadata instance representing the custom component. This should be an instance of an appropriate
+ * <code>MutableMetadata</code> type to enable further decoration by other namespace handlers
+ */
+ Metadata parse(Element element, ParserContext context);
+
+ /**
+ * Process a child node of an enclosing blueprint component.
+ *
+ * If the decorator method returns a new <code>ComponentMetadata</code> instance, this will replace the argument
+ * <code>ComponentMetadata</code> in subsequent parsing and namespace handler invocations. A namespace
+ * handler that elects to return a new <code>ComponentMetadata</code> instance should
+ * ensure that existing interceptors are registered against the new instance if appropriate.
+ *
+ * Due to the interaction with interceptors, a namespace handler should prefer to change a component metadata
+ * instead of returning a new instance wherever possible. This can be achieved by casting a
+ * <code>ComponentMetadata</code> to its corresponding <code>MutabableComponentMetadata</code> instance.
+ * Note however that a given <code>ComponentMetadata</code> instance cannot be guaranteed to implement
+ * the mutable interface if it was constructed by an agent other than the blueprint extender.
+ *
+ * @param node The node associated with this NamespaceHandler that should be used to decorate the enclosing
+ * component
+ * @param component The enclosing blueprint component
+ * @param context The parser context
+ * @return The decorated component to be used instead of the original enclosing component. This can of course be
+ * the original component.
+ */
+ ComponentMetadata decorate(Node node, ComponentMetadata component, ParserContext context);
+
+}
Added: aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ParserContext.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ParserContext.java?rev=1075147&view=auto
==============================================================================
--- aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ParserContext.java (added)
+++ aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ParserContext.java Sun Feb 27 21:05:07 2011
@@ -0,0 +1,90 @@
+/**
+ * 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;
+
+import org.osgi.service.blueprint.reflect.ComponentMetadata;
+import org.osgi.service.blueprint.reflect.Metadata;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+public interface ParserContext {
+ /**
+ * Returns the DOM Node that was passed to the NamespaceHandler call for which
+ * this ParserContext instance was created.
+ */
+ Node getSourceNode();
+
+ ComponentDefinitionRegistry getComponentDefinitionRegistry();
+
+ /**
+ * Retrieve the <code>ComponentMetadata</code> of the component that
+ * encloses the current <code>Node</code> that is to be parsed by a
+ * namespace handler.
+ *
+ * In case of top-level components this method will return <code>null</code>.
+ * @returns the enclosing component's metadata or null if there is no enclosing component
+ */
+ ComponentMetadata getEnclosingComponent();
+
+ /**
+ * Create a new metadata instance of the given type. The returned
+ * object will also implement the appropriate <code>MutableComponentMetadata</code>
+ * interface, so as to allow the caller to set the properties of the
+ * metadata.
+ *
+ * Note that the returned object may not be initialised, so callers
+ * should take care to assure every property needed by the blueprint
+ * extender is set.
+ *
+ * @param type the class of the Metadata object to create
+ * @param <T> The expected Metadata type to be created
+ * @return a new instance
+ */
+ <T extends Metadata> T createMetadata(Class<T> type);
+
+ /**
+ * Invoke the blueprint parser to parse a DOM element.
+ * @param type the class of the Metadata type to be parsed
+ * @param enclosingComponent The component metadata that contains the Element
+ * to be parsed
+ * @param element The DOM element that is to be parsed
+ * @param <T> The expected metadata type to be parsed
+ */
+ <T> T parseElement(Class<T> type, ComponentMetadata enclosingComponent, Element element);
+
+ /**
+ * Generate a unique id following the same scheme that the blueprint container
+ * uses internally
+ */
+ String generateId();
+
+ /**
+ * Get the default activation setting for the current blueprint file
+ */
+ String getDefaultActivation();
+
+ /**
+ * Get the default availability setting for the current blueprint file
+ */
+ String getDefaultAvailability();
+
+ /**
+ * Get the default timeout setting for the current blueprint file
+ */
+ String getDefaultTimeout();
+}
+
Added: aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ParserService.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ParserService.java?rev=1075147&view=auto
==============================================================================
--- aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ParserService.java (added)
+++ aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ParserService.java Sun Feb 27 21:05:07 2011
@@ -0,0 +1,87 @@
+/**
+ * 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;
+
+import java.io.InputStream;
+import java.net.URL;
+import java.util.List;
+
+import org.osgi.framework.Bundle;
+
+public interface ParserService {
+
+ /**
+ * Parse a single InputStream containing blueprint xml. No validation will be performed. The caller
+ * is responsible for closing the InputStream afterwards.
+ * @param is InputStream containing blueprint xml.
+ * @param clientBundle The client's bundle
+ * @return ComponentDefinitionRegistry containing metadata generated by the parser.
+ * @throws Exception
+ */
+ ComponentDefinitionRegistry parse (InputStream is, Bundle clientBundle) throws Exception;
+
+ /**
+ * Parse a single InputStream containing blueprint xml. The caller is responsible for
+ * closing the InputStream afterwards.
+ * @param is Input stream containing blueprint xml
+ * @param clientBundle The client's bundle
+ * @param validate Indicates whether or not to validate the blueprint xml
+ * @return ComponentDefinitionRegistry containing metadata generated by the parser.
+ * @throws Exception
+ */
+ ComponentDefinitionRegistry parse (InputStream is, Bundle clientBundle, boolean validate) throws Exception;
+
+ /**
+ * Parse blueprint xml referred to by a single URL. No validation will be performed.
+ * @param url URL reference to the blueprint xml to parse
+ * @param clientBundle The client's bundle
+ * @return ComponentDefinitionRegistry containing metadata generated by the parser.
+ * @throws Exception
+ */
+ ComponentDefinitionRegistry parse (URL url, Bundle clientBundle) throws Exception;
+
+ /**
+ * Parse blueprint xml referred to by a single URL.
+ * @param url URL reference to the blueprint xml to parse
+ * @param clientBundle The client's bundle
+ * @param validate Indicates whether or not to validate the blueprint xml
+ * @return ComponentDefinitionRegistry containing metadata generated by the parser.
+ * @throws Exception
+ */
+ ComponentDefinitionRegistry parse (URL url, Bundle clientBundle, boolean validate) throws Exception;
+
+ /**
+ * Parse blueprint xml referred to by a list of URLs. No validation will be performed.
+ * @param urls URL reference to the blueprint xml to parse
+ * @param clientBundle The client's bundle
+ * @return ComponentDefinitionRegistry containing metadata generated by the parser.
+ * @throws Exception
+ */
+ ComponentDefinitionRegistry parse (List<URL> urls, Bundle clientBundle) throws Exception;
+
+ /**
+ * Parse blueprint xml referred to by a list of URLs.
+ * @param urls URL reference to the blueprint xml to parse
+ * @param clientBundle The client's bundle
+ * @param validate Indicates whether or not to validate the blueprint xml
+ * @return ComponentDefinitionRegistry containing metadata generated by the parser.
+ * @throws Exception
+ */
+ ComponentDefinitionRegistry parse (List<URL> urls, Bundle clientBundle, boolean validate) throws Exception;
+
+}
Added: aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/PassThroughMetadata.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/PassThroughMetadata.java?rev=1075147&view=auto
==============================================================================
--- aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/PassThroughMetadata.java (added)
+++ aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/PassThroughMetadata.java Sun Feb 27 21:05:07 2011
@@ -0,0 +1,33 @@
+/**
+ * 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;
+
+import org.osgi.service.blueprint.reflect.ComponentMetadata;
+import org.osgi.service.blueprint.reflect.Target;
+
+/**
+ * Metadata used to bypass the creation of the object.
+ * This is mostly usefull when creating custom namespace handlers
+ * that end-up with already instanciated objects.
+ */
+public interface PassThroughMetadata extends ComponentMetadata, Target {
+
+ Object getObject();
+
+}
Added: aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/Processor.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/Processor.java?rev=1075147&view=auto
==============================================================================
--- aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/Processor.java (added)
+++ aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/Processor.java Sun Feb 27 21:05:07 2011
@@ -0,0 +1,25 @@
+/**
+ * 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;
+
+/**
+ * Marker interface for blueprint processors such as <code>BeanProcessor</code> or
+ * <code>ServiceProcessor</code>
+ */
+public interface Processor {}
Added: aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ServiceProcessor.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ServiceProcessor.java?rev=1075147&view=auto
==============================================================================
--- aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ServiceProcessor.java (added)
+++ aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/ServiceProcessor.java Sun Feb 27 21:05:07 2011
@@ -0,0 +1,36 @@
+/**
+ * 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;
+
+import java.util.Dictionary;
+
+/**
+ */
+public interface ServiceProcessor extends Processor {
+
+ void updateProperties(ServicePropertiesUpdater service, Dictionary properties);
+
+ interface ServicePropertiesUpdater {
+
+ String getId();
+
+ void updateProperties(Dictionary properties);
+
+ }
+}
Added: aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/container/AbstractServiceReferenceRecipe.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/container/AbstractServiceReferenceRecipe.java?rev=1075147&view=auto
==============================================================================
--- aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/container/AbstractServiceReferenceRecipe.java (added)
+++ aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/container/AbstractServiceReferenceRecipe.java Sun Feb 27 21:05:07 2011
@@ -0,0 +1,533 @@
+/*
+ * 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.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.aries.blueprint.BlueprintConstants;
+import org.apache.aries.blueprint.ExtendedBlueprintContainer;
+import org.apache.aries.blueprint.ExtendedServiceReferenceMetadata;
+import org.apache.aries.blueprint.di.AbstractRecipe;
+import org.apache.aries.blueprint.di.CollectionRecipe;
+import org.apache.aries.blueprint.di.Recipe;
+import org.apache.aries.blueprint.utils.BundleDelegatingClassLoader;
+import org.apache.aries.blueprint.utils.ReflectionUtils;
+import org.apache.aries.proxy.UnableToProxyException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.blueprint.container.ComponentDefinitionException;
+import org.osgi.service.blueprint.container.ReifiedType;
+import org.osgi.service.blueprint.reflect.ReferenceListener;
+import org.osgi.service.blueprint.reflect.ReferenceMetadata;
+import org.osgi.service.blueprint.reflect.ServiceReferenceMetadata;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Abstract class for service reference recipes.
+ *
+ * TODO: if we have a single interface (which is the standard behavior), then we should be able to get rid of
+ * the proxyClassloader and just use this interface classloader to define the proxy
+ *
+ * TODO: it is allowed to have no interface defined at all, which should result in an empty proxy
+ *
+ * @version $Rev: 1030761 $, $Date: 2010-11-03 23:48:47 +0000 (Wed, 03 Nov 2010) $
+ */
+public abstract class AbstractServiceReferenceRecipe extends AbstractRecipe implements ServiceListener, SatisfiableRecipe {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(AbstractServiceReferenceRecipe.class);
+
+ protected final ExtendedBlueprintContainer blueprintContainer;
+ protected final ServiceReferenceMetadata metadata;
+ protected final CollectionRecipe listenersRecipe;
+ protected final List<Recipe> explicitDependencies;
+ protected final boolean optional;
+ /** The OSGi filter for tracking references */
+ protected final String filter;
+ /** The list of listeners for this reference. This list will be lazy created */
+ protected List<Listener> listeners;
+
+ private final List<ServiceReference> references = new ArrayList<ServiceReference>();
+ private final AtomicBoolean started = new AtomicBoolean();
+ private final AtomicBoolean satisfied = new AtomicBoolean();
+ private SatisfactionListener satisfactionListener;
+
+ protected AbstractServiceReferenceRecipe(String name,
+ ExtendedBlueprintContainer blueprintContainer,
+ ServiceReferenceMetadata metadata,
+ CollectionRecipe listenersRecipe,
+ List<Recipe> explicitDependencies) {
+ super(name);
+ this.prototype = false;
+ this.blueprintContainer = blueprintContainer;
+ this.metadata = metadata;
+ this.listenersRecipe = listenersRecipe;
+ this.explicitDependencies = explicitDependencies;
+
+
+ this.optional = (metadata.getAvailability() == ReferenceMetadata.AVAILABILITY_OPTIONAL);
+ this.filter = createOsgiFilter(metadata);
+ }
+
+
+
+ public CollectionRecipe getListenersRecipe() {
+ return listenersRecipe;
+ }
+
+ public void start(SatisfactionListener listener) {
+ if (listener == null) throw new NullPointerException("satisfactionListener is null");
+ if (started.compareAndSet(false, true)) {
+ try {
+ satisfactionListener = listener;
+ satisfied.set(optional);
+ // Synchronized block on references so that service events won't interfere with initial references tracking
+ // though this may not be sufficient because we don't control ordering of those events
+ synchronized (references) {
+ blueprintContainer.getBundleContext().addServiceListener(this, getOsgiFilter());
+ ServiceReference[] references = blueprintContainer.getBundleContext().getServiceReferences(null, getOsgiFilter());
+ if (references != null) {
+ for (ServiceReference reference : references) {
+ this.references.add(reference);
+ track(reference);
+ }
+ satisfied.set(optional || !this.references.isEmpty());
+ }
+ LOGGER.debug("Found initial references {} for OSGi service {}", references, getOsgiFilter());
+ }
+ } catch (InvalidSyntaxException e) {
+ throw new ComponentDefinitionException(e);
+ }
+ }
+ }
+
+ public void stop() {
+ if (started.compareAndSet(true, false)) {
+ synchronized (references) {
+ blueprintContainer.getBundleContext().removeServiceListener(this);
+ doStop();
+ for (Iterator<ServiceReference> it = references.iterator(); it.hasNext();) {
+ ServiceReference ref = it.next();
+ it.remove();
+ untrack(ref);
+ }
+ satisfied.set(false);
+ }
+ }
+ }
+
+ protected void doStop() {
+ }
+
+ protected boolean isStarted() {
+ return started.get();
+ }
+
+ public boolean isSatisfied() {
+ return satisfied.get();
+ }
+
+ @Override
+ public List<Recipe> getConstructorDependencies() {
+ List<Recipe> recipes = new ArrayList<Recipe>();
+ if (explicitDependencies != null) {
+ recipes.addAll(explicitDependencies);
+ }
+ return recipes;
+ }
+
+ public List<Recipe> getDependencies() {
+ List<Recipe> recipes = new ArrayList<Recipe>();
+ if (listenersRecipe != null) {
+ recipes.add(listenersRecipe);
+ }
+ recipes.addAll(getConstructorDependencies());
+ return recipes;
+ }
+
+ public String getOsgiFilter() {
+ return filter;
+ }
+
+ protected void createListeners() {
+ if (listenersRecipe != null) {
+ List<Listener> listeners = (List<Listener>) listenersRecipe.create();
+ for (Listener listener : listeners) {
+ List<Class> classList = new ArrayList<Class>();
+ Class clz = getInterfaceClass();
+ if (clz != null) {
+ classList.add(clz);
+ } else {
+ classList.add(Object.class);
+ }
+ listener.init(classList);
+ }
+ this.listeners = listeners;
+ } else {
+ this.listeners = Collections.emptyList();
+ }
+ }
+
+ protected List<Class<?>> loadAllClasses(Iterable<String> interfaceNames) {
+ List<Class<?>> classes = new ArrayList<Class<?>>();
+ for (String name : interfaceNames) {
+ Class<?> clazz = loadClass(name);
+ classes.add(clazz);
+ }
+ return classes;
+ }
+
+ protected ReifiedType loadType(String typeName, ClassLoader fromClassLoader) {
+ if (typeName == null) {
+ return null;
+ }
+ try {
+ // this method is overriden to use the blueprint container directly
+ // because proxies can be created outside of the recipe creation which
+ // would lead to an exception because the context is not set
+ // TODO: consider having the context as a property on the recipe rather than a thread local
+ return GenericType.parse(typeName, fromClassLoader != null ? fromClassLoader : blueprintContainer);
+ } catch (ClassNotFoundException e) {
+ throw new ComponentDefinitionException("Unable to load class " + typeName + " from recipe " + this, e);
+ }
+ }
+
+
+ protected Object createProxy(final Callable<Object> dispatcher, Set<Class<?>> interfaces) throws Exception {
+ if (!interfaces.iterator().hasNext()) {
+ return new Object();
+ } else {
+ return BlueprintExtender.getProxyManager().createProxy(blueprintContainer.getBundleContext().getBundle(), interfaces, dispatcher);
+ }
+ }
+
+ public void serviceChanged(ServiceEvent event) {
+ int eventType = event.getType();
+ ServiceReference ref = event.getServiceReference();
+ switch (eventType) {
+ case ServiceEvent.REGISTERED:
+ serviceAdded(ref);
+ break;
+ case ServiceEvent.MODIFIED:
+ serviceModified(ref);
+ break;
+ case ServiceEvent.UNREGISTERING:
+ serviceRemoved(ref);
+ break;
+ }
+ }
+
+ private void serviceAdded(ServiceReference ref) {
+ LOGGER.debug("Tracking reference {} for OSGi service {}", ref, getOsgiFilter());
+ synchronized (references) {
+ references.add(ref);
+ }
+ track(ref);
+ setSatisfied(true);
+ }
+
+ private void serviceModified(ServiceReference ref) {
+ // ref must be in references and must be satisfied
+ track(ref);
+ }
+
+ private void serviceRemoved(ServiceReference ref) {
+ LOGGER.debug("Untracking reference {} for OSGi service {}", ref, getOsgiFilter());
+ boolean removed;
+ boolean satisfied;
+ synchronized (references) {
+ removed = references.remove(ref);
+ satisfied = optional || !references.isEmpty();
+ }
+ if (removed) {
+ untrack(ref);
+ }
+ setSatisfied(satisfied);
+ }
+
+ protected Class getInterfaceClass() {
+ Class clz = getRuntimeClass(metadata);
+ if (clz != null)
+ return clz;
+ else if (metadata.getInterface() != null)
+ return loadClass(metadata.getInterface());
+ return null;
+ }
+
+ protected static Class getRuntimeClass(ServiceReferenceMetadata metadata) {
+ if (metadata instanceof ExtendedServiceReferenceMetadata && ((ExtendedServiceReferenceMetadata) metadata).getRuntimeInterface() != null) {
+ return ((ExtendedServiceReferenceMetadata) metadata).getRuntimeInterface();
+ }
+ return null;
+ }
+
+ protected void setSatisfied(boolean s) {
+ // This check will ensure an atomic comparision and set
+ // so that it will only be true if the value actually changed
+ if (satisfied.getAndSet(s) != s) {
+ LOGGER.debug("Service reference with filter {} satisfied {}", getOsgiFilter(), this.satisfied);
+ this.satisfactionListener.notifySatisfaction(this);
+ }
+ }
+
+ protected abstract void track(ServiceReference reference);
+
+ protected abstract void untrack(ServiceReference reference);
+
+ protected abstract void retrack();
+
+ protected void updateListeners() {
+ if (references.isEmpty()) {
+ unbind(null, null);
+ } else {
+ retrack();
+ }
+ }
+
+ protected void bind(ServiceReference reference, Object service) {
+ if (listeners != null) {
+ for (Listener listener : listeners) {
+ if (listener != null) {
+ listener.bind(reference, service);
+ }
+ }
+ }
+ }
+
+ protected void unbind(ServiceReference reference, Object service) {
+ if (listeners != null) {
+ for (Listener listener : listeners) {
+ if (listener != null) {
+ listener.unbind(reference, service);
+ }
+ }
+ }
+ }
+
+ public List<ServiceReference> getServiceReferences() {
+ synchronized (references) {
+ return new ArrayList<ServiceReference>(references);
+ }
+ }
+
+ public ServiceReference getBestServiceReference() {
+ synchronized (references) {
+ int length = references.size();
+ if (length == 0) { /* if no service is being tracked */
+ return null;
+ }
+ int index = 0;
+ if (length > 1) { /* if more than one service, select highest ranking */
+ int maxRanking = Integer.MIN_VALUE;
+ long minId = Long.MAX_VALUE;
+ for (int i = 0; i < length; i++) {
+ Object property = references.get(i).getProperty(Constants.SERVICE_RANKING);
+ int ranking = (property instanceof Integer) ? (Integer) property : 0;
+ long id = (Long) references.get(i).getProperty(Constants.SERVICE_ID);
+ if ((ranking > maxRanking) || (ranking == maxRanking && id < minId)) {
+ index = i;
+ maxRanking = ranking;
+ minId = id;
+ }
+ }
+ }
+ return references.get(index);
+ }
+ }
+
+ public static class Listener {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(Listener.class);
+
+ private Object listener;
+ private ReferenceListener metadata;
+ private ExtendedBlueprintContainer blueprintContainer;
+
+ private Set<Method> bindMethodsReference = new HashSet<Method>();
+ private Set<Method> bindMethodsObjectProp = new HashSet<Method>();
+ private Set<Method> bindMethodsObject = new HashSet<Method>();
+ private Set<Method> unbindMethodsReference = new HashSet<Method>();
+ private Set<Method> unbindMethodsObject = new HashSet<Method>();
+ private Set<Method> unbindMethodsObjectProp = new HashSet<Method>();
+
+ public void setListener(Object listener) {
+ this.listener = listener;
+ }
+
+ public void setMetadata(ReferenceListener metadata) {
+ this.metadata = metadata;
+ }
+
+ public void setBlueprintContainer(ExtendedBlueprintContainer blueprintContainer) {
+ this.blueprintContainer = blueprintContainer;
+ }
+
+ public void init(Collection<Class> classes) {
+ Set<Class> clazzes = new HashSet<Class>(classes);
+ clazzes.add(Object.class);
+ Class listenerClass = listener.getClass();
+ String bindName = metadata.getBindMethod();
+ if (bindName != null) {
+ bindMethodsReference.addAll(ReflectionUtils.findCompatibleMethods(listenerClass, bindName, new Class[] { ServiceReference.class }));
+ for (Class clazz : clazzes) {
+ bindMethodsObject.addAll(ReflectionUtils.findCompatibleMethods(listenerClass, bindName, new Class[] { clazz }));
+ bindMethodsObjectProp.addAll(ReflectionUtils.findCompatibleMethods(listenerClass, bindName, new Class[] { clazz, Map.class }));
+ }
+ if (bindMethodsReference.size() + bindMethodsObject.size() + bindMethodsObjectProp.size() == 0) {
+ throw new ComponentDefinitionException("No matching methods found for listener bind method: " + bindName);
+ }
+ }
+ String unbindName = metadata.getUnbindMethod();
+ if (unbindName != null) {
+ unbindMethodsReference.addAll(ReflectionUtils.findCompatibleMethods(listenerClass, unbindName, new Class[] { ServiceReference.class }));
+ for (Class clazz : clazzes) {
+ unbindMethodsObject.addAll(ReflectionUtils.findCompatibleMethods(listenerClass, unbindName, new Class[] { clazz }));
+ unbindMethodsObjectProp.addAll(ReflectionUtils.findCompatibleMethods(listenerClass, unbindName, new Class[] { clazz, Map.class }));
+ }
+ if (unbindMethodsReference.size() + unbindMethodsObject.size() + unbindMethodsObjectProp.size() == 0) {
+ throw new ComponentDefinitionException("No matching methods found for listener unbind method: " + unbindName);
+ }
+ }
+ }
+
+ public void bind(ServiceReference reference, Object service) {
+ invokeMethods(bindMethodsReference, bindMethodsObject, bindMethodsObjectProp, reference, service);
+ }
+
+ public void unbind(ServiceReference reference, Object service) {
+ invokeMethods(unbindMethodsReference, unbindMethodsObject, unbindMethodsObjectProp, reference, service);
+ }
+
+ private void invokeMethods(Set<Method> referenceMethods, Set<Method> objectMethods, Set<Method> objectPropMethods, ServiceReference reference, Object service) {
+ for (Method method : referenceMethods) {
+ try {
+ ReflectionUtils.invoke(blueprintContainer.getAccessControlContext(),
+ method, listener, reference);
+ } catch (Exception e) {
+ LOGGER.error("Error calling listener method " + method, e);
+ }
+ }
+ for (Method method : objectMethods) {
+ try {
+ ReflectionUtils.invoke(blueprintContainer.getAccessControlContext(),
+ method, listener, service);
+ } catch (Exception e) {
+ LOGGER.error("Error calling listener method " + method, e);
+ }
+ }
+ Map<String, Object> props = null;
+ for (Method method : objectPropMethods) {
+ if (props == null) {
+ props = new HashMap<String, Object>();
+ if (reference != null) {
+ for (String name : reference.getPropertyKeys()) {
+ props.put(name, reference.getProperty(name));
+ }
+ }
+ }
+ try {
+ ReflectionUtils.invoke(blueprintContainer.getAccessControlContext(),
+ method, listener, service, props);
+ } catch (Exception e) {
+ LOGGER.error("Error calling listener method " + method, e);
+ }
+ }
+ }
+ }
+
+ /**
+ * Create the OSGi filter corresponding to the ServiceReferenceMetadata constraints
+ *
+ * @param metadata the service reference metadata
+ * @return the OSGi filter
+ */
+ private static String createOsgiFilter(ServiceReferenceMetadata metadata) {
+ List<String> members = new ArrayList<String>();
+ // Handle filter
+ String flt = metadata.getFilter();
+ if (flt != null && flt.length() > 0) {
+ if (!flt.startsWith("(")) {
+ flt = "(" + flt + ")";
+ }
+ members.add(flt);
+ }
+ // Handle interfaces
+ String interfaceName = metadata.getInterface();
+ Class runtimeClass = getRuntimeClass(metadata);
+ if (runtimeClass != null) {
+ interfaceName = runtimeClass.getName();
+ }
+ if (interfaceName != null && interfaceName.length() > 0) {
+ members.add("(" + Constants.OBJECTCLASS + "=" + interfaceName + ")");
+ }
+ // Handle component name
+ String componentName = metadata.getComponentName();
+ if (componentName != null && componentName.length() > 0) {
+ members.add("(" + BlueprintConstants.COMPONENT_NAME_PROPERTY + "=" + componentName + ")");
+ }
+ // Create filter
+ if (members.isEmpty()) {
+ throw new IllegalStateException("No constraints were specified on the service reference");
+ }
+ if (members.size() == 1) {
+ return members.get(0);
+ }
+ StringBuilder sb = new StringBuilder("(&");
+ for (String member : members) {
+ sb.append(member);
+ }
+ sb.append(")");
+ return sb.toString();
+ }
+
+ private static Class[] getInterfaces(Class[] classes) {
+ Set<Class> interfaces = new HashSet<Class>();
+ for (Class clazz : classes) {
+ if (clazz.isInterface()) {
+ interfaces.add(clazz);
+ }
+ }
+ return toClassArray(interfaces);
+ }
+
+ private static Class[] toClassArray(Set<Class> classes) {
+ return classes.toArray(new Class [classes.size()]);
+ }
+
+}