/*
* 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.brooklyn.core.mgmt.classloading;
import java.net.URL;
import java.util.Collection;
import java.util.Collections;
import org.apache.brooklyn.api.mgmt.ManagementContext;
import org.apache.brooklyn.api.typereg.OsgiBundleWithUrl;
import org.apache.brooklyn.api.typereg.RegisteredType;
import org.apache.brooklyn.core.mgmt.entitlement.Entitlements;
import org.apache.brooklyn.core.mgmt.ha.OsgiManager;
import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
import org.apache.brooklyn.util.guava.Maybe;
import com.google.common.base.Objects;
public class OsgiBrooklynClassLoadingContext extends AbstractBrooklynClassLoadingContext {
private final String catalogItemId;
private boolean hasBundles = false;
private transient Collection<? extends OsgiBundleWithUrl> _bundles;
public OsgiBrooklynClassLoadingContext(ManagementContext mgmt, String catalogItemId, Collection<? extends OsgiBundleWithUrl> bundles) {
super(mgmt);
this._bundles = bundles;
this.hasBundles = bundles!=null && !bundles.isEmpty();
this.catalogItemId = catalogItemId;
}
public Collection<? extends OsgiBundleWithUrl> getBundles() {
if (_bundles!=null || !hasBundles) return _bundles;
RegisteredType item = mgmt.getTypeRegistry().get(catalogItemId);
if (item==null) {
throw new IllegalStateException("Catalog item not found for "+catalogItemId+"; cannot create loading context");
}
_bundles = item.getLibraries();
return _bundles;
}
@Override
@SuppressWarnings({ "unchecked", "rawtypes" })
public Maybe<Class<?>> tryLoadClass(String className) {
Maybe<Class<Object>> clazz = null;
Maybe<OsgiManager> osgi = null;
if (mgmt!=null) {
osgi = ((ManagementContextInternal)mgmt).getOsgiManager();
if (osgi.isPresent() && getBundles()!=null && !getBundles().isEmpty()) {
if (!Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.SEE_CATALOG_ITEM, catalogItemId))
return Maybe.absent("Not entitled to use this catalog entry");
clazz = osgi.get().tryResolveClass(className, getBundles());
if (clazz.isPresent())
return (Maybe)clazz;
}
}
if (clazz!=null) {
// if OSGi bundles were defined and failed, then use its error message
return (Maybe)clazz;
}
// else determine best message
if (mgmt==null) return Maybe.absent("No mgmt context available for loading "+className);
if (osgi!=null && osgi.isAbsent()) return Maybe.absent("OSGi not available on mgmt for loading "+className);
if (!hasBundles)
return Maybe.absent("No bundles available for loading "+className);
return Maybe.absent("Inconsistent state ("+mgmt+"/"+osgi+"/"+getBundles()+" loading "+className);
}
@Override
public String toString() {
return "OSGi:"+catalogItemId+"["+getBundles()+"]";
}
@Override
public int hashCode() {
return Objects.hashCode(super.hashCode(), getBundles(), catalogItemId);
}
@Override
public boolean equals(Object obj) {
if (!super.equals(obj)) return false;
if (!(obj instanceof OsgiBrooklynClassLoadingContext)) return false;
OsgiBrooklynClassLoadingContext other = (OsgiBrooklynClassLoadingContext)obj;
if (!catalogItemId.equals(other.catalogItemId)) return false;
if (!Objects.equal(getBundles(), other.getBundles())) return false;
return true;
}
@Override
public URL getResource(String name) {
if (mgmt != null && isEntitledToSeeCatalogItem()) {
Maybe<OsgiManager> osgi = ((ManagementContextInternal) mgmt).getOsgiManager();
if (osgi.isPresent() && hasBundles) {
return osgi.get().getResource(name, getBundles());
}
}
return null;
}
@Override
public Iterable<URL> getResources(String name) {
if (mgmt != null && isEntitledToSeeCatalogItem()) {
Maybe<OsgiManager> osgi = ((ManagementContextInternal) mgmt).getOsgiManager();
if (osgi.isPresent() && hasBundles) {
return osgi.get().getResources(name, getBundles());
}
}
return Collections.emptyList();
}
public String getCatalogItemId() {
return catalogItemId;
}
/**
* @return true if the current entitlement context may {@link Entitlements#SEE_CATALOG_ITEM see}
* {@link #getCatalogItemId}.
*/
private boolean isEntitledToSeeCatalogItem() {
return Entitlements.isEntitled(mgmt.getEntitlementManager(),
Entitlements.SEE_CATALOG_ITEM,
catalogItemId);
}
}