package org.gcube.smartgears.handlers.application.lifecycle; import static org.gcube.smartgears.handlers.ProfileEvents.published; import static org.gcube.smartgears.utils.Utils.notEmpty; import static org.gcube.smartgears.utils.Utils.rethrowUnchecked; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.gcube.common.authorization.library.provider.SecurityTokenProvider; import org.gcube.common.resources.gcore.GCoreEndpoint; import org.gcube.common.scope.api.ScopeProvider; import org.gcube.informationsystem.publisher.ScopedPublisher; import org.gcube.smartgears.configuration.Mode; import org.gcube.smartgears.context.application.ApplicationContext; import org.gcube.smartgears.handlers.ProfilePublisher; import org.gcube.smartgears.provider.ProviderFactory; import org.gcube.smartgears.security.AuthorizationProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Publishes the current resource profile of the application. *

*Distinguishes publication in new scopes ({@link #addTo(List)} from publication updates in existing scopes ({@link #update()}. * * * @author Fabio Simeoni * */ public class ProfilePublisherImpl implements ProfilePublisher { private static final Logger log = LoggerFactory.getLogger(ProfilePublisherImpl.class); //the underlying IS publisher private final ScopedPublisher publisher; private final ApplicationContext context; private AuthorizationProvider authProxy ; /** * Creates an instance for a given application. * @param context the context of the application */ public ProfilePublisherImpl(ApplicationContext context) { this.context = context; this.publisher=ProviderFactory.provider().publisherFor(context); this.authProxy = context.container().configuration().authorizationProvider(); } /** * Adds for the first time the current resource profile of the application in one or more scopes. * @param scopes the scopes */ @Override public void addTo(Collection contexts) { notEmpty("tokens",contexts); GCoreEndpoint profile = context.profile(GCoreEndpoint.class); /* TODO: reintroduce it when scope will be removed //TODO: remove when move to new IS Collection retainedContexts = new ArrayList(context.container().configuration().allowedContexts()); retainedContexts.removeAll(profile.scopes().asCollection()); profile.scopes().asCollection().addAll(retainedContexts); String previousToken = SecurityTokenProvider.instance.get(); try { for (String token: tokens){ log.info("creating profile with token {}", token); SecurityTokenProvider.instance.set(token); profile = publisher.create(profile); SecurityTokenProvider.instance.reset(); } }catch (Exception e) { rethrowUnchecked(e); } finally{ SecurityTokenProvider.instance.set(previousToken); } */ ClassLoader contextCL = Thread.currentThread().getContextClassLoader(); log.debug("using context {}",contextCL.getClass().getSimpleName()); String previousToken = SecurityTokenProvider.instance.get(); String previousScope = ScopeProvider.instance.get(); try{//This classloader set is needed for the jaxb context if (previousToken!=null) SecurityTokenProvider.instance.reset();; if (context.container().configuration().mode()!=Mode.root) Thread.currentThread().setContextClassLoader(ProfilePublisherImpl.class.getClassLoader()); ScopeProvider.instance.set(contexts.stream().findFirst().get()); profile = publisher.create(profile, new ArrayList(contexts)); } catch (Exception e) { rethrowUnchecked(e); } finally{ SecurityTokenProvider.instance.set(previousToken); ScopeProvider.instance.set(previousScope); if (context.container().configuration().mode()!=Mode.root) Thread.currentThread().setContextClassLoader(contextCL); } sharePublished(profile); log.debug("shared profile with scopes {}", profile.scopes().asCollection()); } @Override public void addToAll() { this.addTo(context.configuration().allowedContexts()); } @Override public void update() { GCoreEndpoint profile = context.profile(GCoreEndpoint.class); ClassLoader contextCL = Thread.currentThread().getContextClassLoader(); log.debug("using context {}",contextCL.getClass().getSimpleName()); String previousToken = SecurityTokenProvider.instance.get(); String previousScope = ScopeProvider.instance.get(); try{//This classloader set is needed for the jaxb context if (previousToken!=null) SecurityTokenProvider.instance.reset(); if (context.container().configuration().mode()!=Mode.root) Thread.currentThread().setContextClassLoader(ProfilePublisherImpl.class.getClassLoader()); profile = publisher.update(profile); } catch (Exception e) { rethrowUnchecked(e); } finally{ SecurityTokenProvider.instance.set(previousToken); ScopeProvider.instance.set(previousScope); if (context.container().configuration().mode()!=Mode.root) Thread.currentThread().setContextClassLoader(contextCL); } sharePublished(profile); } /** * Removes the application from one or more scopes. * @param scopes the scopes */ @Override public void removeFrom(Collection contexts) { GCoreEndpoint profile = context.profile(GCoreEndpoint.class); ClassLoader contextCL = Thread.currentThread().getContextClassLoader(); log.debug("using context {}",contextCL.getClass().getSimpleName()); String previousToken = SecurityTokenProvider.instance.get(); String previousScope = ScopeProvider.instance.get(); try{//This classloader set is needed for the jaxb context if (previousToken!=null) SecurityTokenProvider.instance.reset(); if (context.container().configuration().mode()!=Mode.root) Thread.currentThread().setContextClassLoader(ProfilePublisherImpl.class.getClassLoader()); profile = publisher.remove(profile, contexts); } catch (Exception e) { rethrowUnchecked(e); } finally{ SecurityTokenProvider.instance.set(previousToken); ScopeProvider.instance.set(previousScope); if (context.container().configuration().mode()!=Mode.root) Thread.currentThread().setContextClassLoader(contextCL); } log.debug("after remove application profile contains scopes {}",profile.scopes().asCollection()); sharePublished(profile); } private void sharePublished(GCoreEndpoint profile) { context.events().fire(profile,published); } private List resolveScopesFromTokens(Collection tokens){ List scopes = new ArrayList(tokens.size()); for (String token: tokens) try{ scopes.add(this.authProxy.get(token).getContext()); }catch (Exception e) { log.warn("error retrieving token {} , it should never happen",token); } return scopes; } }