mirror of https://github.com/apache/jclouds.git
Improved discovery of api metadata inside OSGi.
This commit is contained in:
parent
4704e29941
commit
cf94e70a95
|
@ -0,0 +1,46 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds 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.jclouds.apis;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A registry for holding {@link org.jclouds.apis.ApiMetadata}.
|
||||||
|
*/
|
||||||
|
public class ApiRegistry {
|
||||||
|
|
||||||
|
private static final Set<ApiMetadata> apis = new HashSet<ApiMetadata>();
|
||||||
|
|
||||||
|
public static void registerApi(ApiMetadata api) {
|
||||||
|
apis.add(api);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void unRegisterApi(ApiMetadata api) {
|
||||||
|
apis.remove(api);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Iterable<ApiMetadata> fromRegistry() {
|
||||||
|
return Iterable.class.cast(apis);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void clear() {
|
||||||
|
apis.clear();
|
||||||
|
}
|
||||||
|
}
|
|
@ -69,7 +69,7 @@ public class Apis {
|
||||||
* @return all available apis
|
* @return all available apis
|
||||||
*/
|
*/
|
||||||
public static Iterable<ApiMetadata> all() {
|
public static Iterable<ApiMetadata> all() {
|
||||||
return fromServiceLoader();
|
return Iterables.concat(fromServiceLoader(), ApiRegistry.fromRegistry());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -18,13 +18,14 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.osgi;
|
package org.jclouds.osgi;
|
||||||
|
|
||||||
|
import org.jclouds.apis.ApiRegistry;
|
||||||
import org.jclouds.providers.ProviderRegistry;
|
import org.jclouds.providers.ProviderRegistry;
|
||||||
import org.osgi.framework.BundleActivator;
|
import org.osgi.framework.BundleActivator;
|
||||||
import org.osgi.framework.BundleContext;
|
import org.osgi.framework.BundleContext;
|
||||||
|
|
||||||
public class Activator implements BundleActivator {
|
public class Activator implements BundleActivator {
|
||||||
|
|
||||||
ProviderBundleListener bundleListener = new ProviderBundleListener();
|
MetadataBundleListener bundleListener = new MetadataBundleListener();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when this bundle is started so the Framework can perform the
|
* Called when this bundle is started so the Framework can perform the
|
||||||
|
@ -67,5 +68,6 @@ public class Activator implements BundleActivator {
|
||||||
public void stop(BundleContext context) throws Exception {
|
public void stop(BundleContext context) throws Exception {
|
||||||
context.removeBundleListener(bundleListener);
|
context.removeBundleListener(bundleListener);
|
||||||
ProviderRegistry.clear();
|
ProviderRegistry.clear();
|
||||||
|
ApiRegistry.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.osgi;
|
package org.jclouds.osgi;
|
||||||
|
|
||||||
|
import org.jclouds.apis.ApiMetadata;
|
||||||
|
import org.jclouds.apis.ApiRegistry;
|
||||||
import org.jclouds.providers.ProviderMetadata;
|
import org.jclouds.providers.ProviderMetadata;
|
||||||
import org.jclouds.providers.ProviderRegistry;
|
import org.jclouds.providers.ProviderRegistry;
|
||||||
import org.osgi.framework.Bundle;
|
import org.osgi.framework.Bundle;
|
||||||
|
@ -32,30 +34,41 @@ import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link BundleListener} that listens for {@link BundleEvent} and searches for {@link org.jclouds.providers.ProviderMetadata} in newly
|
* A {@link BundleListener} that listens for {@link BundleEvent} and searches for {@link org.jclouds.providers.ProviderMetadata} and {@ling org.jclouds.apis.ApiMetadata} in newly
|
||||||
* installed Bundles. This is used as a workaround for OSGi environments where the ServiceLoader cannot cross bundle
|
* installed Bundles. This is used as a workaround for OSGi environments where the ServiceLoader cannot cross bundle
|
||||||
* boundaries.
|
* boundaries.
|
||||||
*/
|
*/
|
||||||
public class ProviderBundleListener implements BundleListener {
|
public class MetadataBundleListener implements BundleListener {
|
||||||
|
|
||||||
private Map<Long, ProviderMetadata> bundleMetadataMap = new HashMap<Long, ProviderMetadata>();
|
private Map<Long, ProviderMetadata> providerMetadataMap = new HashMap<Long, ProviderMetadata>();
|
||||||
|
private Map<Long, ApiMetadata> apiMetadataMap = new HashMap<Long, ApiMetadata>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void bundleChanged(BundleEvent event) {
|
public void bundleChanged(BundleEvent event) {
|
||||||
ProviderMetadata metadata;
|
ProviderMetadata providerMetadata;
|
||||||
|
ApiMetadata apiMetadata;
|
||||||
switch (event.getType()) {
|
switch (event.getType()) {
|
||||||
case BundleEvent.STARTED:
|
case BundleEvent.STARTED:
|
||||||
metadata = getProviderMetadata(event.getBundle());
|
providerMetadata = getProviderMetadata(event.getBundle());
|
||||||
if (metadata != null) {
|
apiMetadata = getApiMetadata(event.getBundle());
|
||||||
ProviderRegistry.registerProvider(metadata);
|
if (providerMetadata != null) {
|
||||||
bundleMetadataMap.put(event.getBundle().getBundleId(), metadata);
|
ProviderRegistry.registerProvider(providerMetadata);
|
||||||
|
providerMetadataMap.put(event.getBundle().getBundleId(), providerMetadata);
|
||||||
|
}
|
||||||
|
if (apiMetadata != null) {
|
||||||
|
ApiRegistry.registerApi(apiMetadata);
|
||||||
|
apiMetadataMap.put(event.getBundle().getBundleId(), apiMetadata);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BundleEvent.STOPPING:
|
case BundleEvent.STOPPING:
|
||||||
case BundleEvent.STOPPED:
|
case BundleEvent.STOPPED:
|
||||||
metadata = bundleMetadataMap.get(event.getBundle().getBundleId());
|
providerMetadata = providerMetadataMap.get(event.getBundle().getBundleId());
|
||||||
if (metadata != null) {
|
apiMetadata = apiMetadataMap.get(event.getBundle().getBundleId());
|
||||||
ProviderRegistry.uRegisterProvider(metadata);
|
if (providerMetadata != null) {
|
||||||
|
ProviderRegistry.uRegisterProvider(providerMetadata);
|
||||||
|
}
|
||||||
|
if (apiMetadata != null) {
|
||||||
|
ApiRegistry.unRegisterApi(apiMetadata);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -72,8 +85,8 @@ public class ProviderBundleListener implements BundleListener {
|
||||||
String className = getProviderMetadataClassName(bundle);
|
String className = getProviderMetadataClassName(bundle);
|
||||||
if (className != null && !className.isEmpty()) {
|
if (className != null && !className.isEmpty()) {
|
||||||
try {
|
try {
|
||||||
Class<? extends ProviderMetadata> provideClass = bundle.loadClass(className);
|
Class<? extends ProviderMetadata> providerMetadataClass = bundle.loadClass(className);
|
||||||
metadata = provideClass.newInstance();
|
metadata = providerMetadataClass.newInstance();
|
||||||
} catch (ClassNotFoundException e) {
|
} catch (ClassNotFoundException e) {
|
||||||
// ignore
|
// ignore
|
||||||
} catch (InstantiationException e) {
|
} catch (InstantiationException e) {
|
||||||
|
@ -86,13 +99,32 @@ public class ProviderBundleListener implements BundleListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the {@link ProviderMetadata} class name for the bundle if it exists.
|
* Creates an instance of {@link ApiMetadata} from the {@link Bundle}.
|
||||||
*
|
*
|
||||||
* @param bundle
|
* @param bundle
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public String getProviderMetadataClassName(Bundle bundle) {
|
public ApiMetadata getApiMetadata(Bundle bundle) {
|
||||||
URL resource = bundle.getEntry("/META-INF/services/org.jclouds.providers.ProviderMetadata");
|
ApiMetadata metadata = null;
|
||||||
|
String className = getApiMetadataClassName(bundle);
|
||||||
|
if (className != null && !className.isEmpty()) {
|
||||||
|
try {
|
||||||
|
Class<? extends ApiMetadata> apiMetadataClass = bundle.loadClass(className);
|
||||||
|
metadata = apiMetadataClass.newInstance();
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
// ignore
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
// ignore
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getMetadataClassName(Bundle bundle, String pathToMetadata) {
|
||||||
|
URL resource = bundle.getEntry(pathToMetadata);
|
||||||
InputStream is = null;
|
InputStream is = null;
|
||||||
InputStreamReader reader = null;
|
InputStreamReader reader = null;
|
||||||
BufferedReader bufferedReader = null;
|
BufferedReader bufferedReader = null;
|
||||||
|
@ -126,4 +158,25 @@ public class ProviderBundleListener implements BundleListener {
|
||||||
}
|
}
|
||||||
return sb.toString().trim();
|
return sb.toString().trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the {@link ProviderMetadata} class name for the bundle if it exists.
|
||||||
|
*
|
||||||
|
* @param bundle
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getProviderMetadataClassName(Bundle bundle) {
|
||||||
|
return getMetadataClassName(bundle, "/META-INF/services/org.jclouds.providers.ProviderMetadata");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the {@link ProviderMetadata} class name for the bundle if it exists.
|
||||||
|
*
|
||||||
|
* @param bundle
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getApiMetadataClassName(Bundle bundle) {
|
||||||
|
return getMetadataClassName(bundle, "/META-INF/services/org.jclouds.apis.ApiMetadata");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue