Author: cziegeler Date: Wed Oct 28 11:09:00 2015 New Revision: 1710993 URL: http://svn.apache.org/viewvc?rev=1710993&view=rev Log: SLING-5162 : Support for the new observation API in the resource resolver. Apply partial patch from Tomek Rekawek
Added: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/observation/ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/observation/BasicObservationReporter.java (with props) sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/observation/BasicObserverConfiguration.java (with props) sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/observation/OsgiObservationBridge.java (with props) sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/observation/ResourceChangeListenerWhiteboard.java (with props) sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/ProviderContextImpl.java (with props) Modified: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/BasicResolveContext.java sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderTracker.java sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/AuthenticatedResourceProvider.java sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/CombinedResourceProvider.java sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/ResourceProviderAuthenticator.java Modified: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/BasicResolveContext.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/BasicResolveContext.java?rev=1710993&r1=1710992&r2=1710993&view=diff ============================================================================== --- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/BasicResolveContext.java (original) +++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/BasicResolveContext.java Wed Oct 28 11:09:00 2015 @@ -18,7 +18,6 @@ */ package org.apache.sling.resourceresolver.impl; -import org.apache.sling.api.SlingException; import org.apache.sling.api.resource.LoginException; import org.apache.sling.api.resource.ResourceResolver; import org.apache.sling.api.resource.ResourceUtil; @@ -96,8 +95,6 @@ public class BasicResolveContext<T> impl } catch ( final LoginException se) { // skip this, try next this.parentProvider = null; - } catch ( final SlingException se) { - // TODO we should rather catch LoginException from getStatefulResourceProvider } if ( this.parentProvider == null ) { path = ResourceUtil.getParent(path); Added: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/observation/BasicObservationReporter.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/observation/BasicObservationReporter.java?rev=1710993&view=auto ============================================================================== --- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/observation/BasicObservationReporter.java (added) +++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/observation/BasicObservationReporter.java Wed Oct 28 11:09:00 2015 @@ -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.sling.resourceresolver.impl.observation; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.sling.api.resource.observation.ResourceChange; +import org.apache.sling.api.resource.observation.ResourceChangeListener; +import org.apache.sling.spi.resource.provider.ObservationReporter; +import org.apache.sling.spi.resource.provider.ObserverConfiguration; + +public class BasicObservationReporter implements ObservationReporter { + + private final Map<ResourceChangeListener, ObserverConfiguration> listeners; + + private final List<ObserverConfiguration> configs; + + public BasicObservationReporter(Map<ResourceChangeListener, ObserverConfiguration> listeners) { + this.listeners = new HashMap<ResourceChangeListener, ObserverConfiguration>(listeners); + this.configs = new ArrayList<ObserverConfiguration>(listeners.values()); + } + + @Override + public List<ObserverConfiguration> getObserverConfigurations() { + return configs; + } + + @Override + public void reportChanges(Iterable<ResourceChange> changes, boolean distribute) { + for (Entry<ResourceChangeListener, ObserverConfiguration> e : listeners.entrySet()) { + List<ResourceChange> filtered = filterChanges(changes, e.getValue()); + e.getKey().onChange(filtered); + } + } + + private List<ResourceChange> filterChanges(Iterable<ResourceChange> changes, ObserverConfiguration config) { + List<ResourceChange> filtered = new ArrayList<ResourceChange>(); + for (ResourceChange c : changes) { + if (matches(c, config)) { + filtered.add(c); + } + } + return filtered; + } + + private boolean matches(ResourceChange change, ObserverConfiguration config) { + if (!config.getChangeTypes().contains(change.getType())) { + return false; + } + if (!config.includeExternal() && change.isExternal()) { + return false; + } + for (String excludedPath : config.getExcludedPaths()) { + if (change.getPath().startsWith(excludedPath)) { + return false; + } + } + boolean included = false; + for (String includedPath : config.getPaths()) { + if (change.getPath().startsWith(includedPath)) { + included = true; + break; + } + } + if (!included) { + return false; + } + return true; + } +} Propchange: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/observation/BasicObservationReporter.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/observation/BasicObservationReporter.java ------------------------------------------------------------------------------ svn:keywords = author date id revision rev url Added: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/observation/BasicObserverConfiguration.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/observation/BasicObserverConfiguration.java?rev=1710993&view=auto ============================================================================== --- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/observation/BasicObserverConfiguration.java (added) +++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/observation/BasicObserverConfiguration.java Wed Oct 28 11:09:00 2015 @@ -0,0 +1,184 @@ +/* + * 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.sling.resourceresolver.impl.observation; + +import static java.util.Arrays.asList; +import static org.apache.sling.api.resource.observation.ResourceChangeListener.CHANGES; +import static org.apache.sling.api.resource.observation.ResourceChangeListener.PATHS; +import static org.apache.sling.commons.osgi.PropertiesUtil.toStringArray; + +import java.util.Collections; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import org.apache.sling.api.resource.observation.ResourceChange.ChangeType; +import org.apache.sling.spi.resource.provider.ObserverConfiguration; + +public class BasicObserverConfiguration implements ObserverConfiguration { + + private final boolean includeExternal; + + private final Set<String> paths; + + private final Set<String> excludedPaths; + + private final Set<ChangeType> changeTypes; + + private BasicObserverConfiguration(Builder builder) { + this.includeExternal = builder.isIncludeExternal(); + this.paths = builder.getPaths(); + this.excludedPaths = builder.getExludedPaths(); + this.changeTypes = builder.getChangeTypes(); + } + + @Override + public boolean includeExternal() { + return includeExternal; + } + + @Override + public Set<String> getPaths() { + return paths; + } + + @Override + public Set<String> getExcludedPaths() { + return excludedPaths; + } + + @Override + public Set<ChangeType> getChangeTypes() { + return changeTypes; + } + + public static class Builder { + private boolean includeExternal; + + private Set<String> paths = Collections.emptySet(); + + private Set<String> excludedPaths = Collections.emptySet(); + + private Set<ChangeType> changeTypes = Collections.emptySet(); + + private String[] searchPaths = new String[0]; + + public boolean isIncludeExternal() { + return includeExternal; + } + + public Builder setIncludeExternal(boolean includeExternal) { + this.includeExternal = includeExternal; + return this; + } + + public Set<String> getPaths() { + return normalizePaths(paths); + } + + public Builder setPaths(Set<String> paths) { + this.paths = paths; + return this; + } + + public Set<String> getExludedPaths() { + return normalizePaths(excludedPaths); + } + + public Builder setExcludedPaths(Set<String> excludedPaths) { + this.excludedPaths = excludedPaths; + return this; + } + + public Set<ChangeType> getChangeTypes() { + return changeTypes; + } + + public Builder setChangeTypes(Set<ChangeType> changeTypes) { + this.changeTypes = changeTypes; + return this; + } + + public Builder setFromProperties(Map<String, Object> properties) { + if (properties.containsKey(PATHS)) { + this.paths = new HashSet<String>(asList(toStringArray(properties.get(PATHS)))); + } else { + this.paths = Collections.emptySet(); + } + if (properties.containsKey(CHANGES)) { + this.changeTypes = EnumSet.noneOf(ChangeType.class); + for (String changeName : toStringArray(properties.get(CHANGES))) { + this.changeTypes.add(ChangeType.valueOf(changeName)); + } + } else { + this.changeTypes = EnumSet.allOf(ChangeType.class); + } + return this; + } + + public Builder setSearchPaths(String[] searchPaths) { + this.searchPaths = searchPaths; + return this; + } + + public ObserverConfiguration build() { + return new BasicObserverConfiguration(this); + } + + private Set<String> normalizePaths(Set<String> relativePaths) { + Set<String> absolutePaths = getAbsolutePaths(relativePaths); + removeSubPaths(absolutePaths); + return absolutePaths; + } + + private static void removeSubPaths(Set<String> absolutePaths) { + Iterator<String> it = absolutePaths.iterator(); + while (it.hasNext()) { + String currentPath = it.next(); + for (String p : absolutePaths) { + if (!p.equals(currentPath) && currentPath.startsWith(p)) { + it.remove(); + break; + } + } + } + } + + private Set<String> getAbsolutePaths(Set<String> relativePaths) { + Set<String> absolutePaths = new HashSet<String>(); + if (relativePaths == null) { + return absolutePaths; + } + for (String path : relativePaths) { + if (path.startsWith("/")) { + absolutePaths.add(path); + } else if (".".equals(path)) { + absolutePaths.add("/"); + } else { + for (String searchPath : searchPaths) { + absolutePaths.add(searchPath + path); + } + } + } + return absolutePaths; + } + } +} Propchange: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/observation/BasicObserverConfiguration.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/observation/BasicObserverConfiguration.java ------------------------------------------------------------------------------ svn:keywords = author date id revision rev url Added: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/observation/OsgiObservationBridge.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/observation/OsgiObservationBridge.java?rev=1710993&view=auto ============================================================================== --- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/observation/OsgiObservationBridge.java (added) +++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/observation/OsgiObservationBridge.java Wed Oct 28 11:09:00 2015 @@ -0,0 +1,180 @@ +/* + * 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.sling.resourceresolver.impl.observation; + +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; + +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.ConfigurationPolicy; +import org.apache.felix.scr.annotations.Properties; +import org.apache.felix.scr.annotations.Property; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.Service; +import org.apache.sling.api.SlingConstants; +import org.apache.sling.api.resource.LoginException; +import org.apache.sling.api.resource.Resource; +import org.apache.sling.api.resource.ResourceResolver; +import org.apache.sling.api.resource.ResourceResolverFactory; +import org.apache.sling.api.resource.observation.ExternalResourceListener; +import org.apache.sling.api.resource.observation.ResourceChange; +import org.apache.sling.api.resource.observation.ResourceChange.ChangeType; +import org.apache.sling.api.resource.observation.ResourceChangeListener; +import org.osgi.service.event.Event; +import org.osgi.service.event.EventAdmin; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Component(policy = ConfigurationPolicy.REQUIRE) +@Service(ResourceChangeListener.class) +@Properties({ @Property(name = ResourceChangeListener.CHANGES, value = { "ADDED", "CHANGED", "REMOVED" }), + @Property(name = ResourceChangeListener.PATHS, value = ".") }) +public class OsgiObservationBridge implements ResourceChangeListener, ExternalResourceListener { + + private static final Logger logger = LoggerFactory.getLogger(OsgiObservationBridge.class); + + @Reference + private EventAdmin eventAdmin; + + @Reference + private ResourceResolverFactory resolverFactory; + + private ResourceResolver resolver; + + private BlockingQueue<ResourceChange> changesQueue; + + private EventSendingJob job; + + @SuppressWarnings("deprecation") + protected void activate() throws LoginException { + resolver = resolverFactory.getAdministrativeResourceResolver(null); + changesQueue = new LinkedBlockingQueue<ResourceChange>(); + job = new EventSendingJob(changesQueue); + Executors.newSingleThreadExecutor().submit(job); + } + + protected void deactivate() { + changesQueue.clear(); + job.stop(); + resolver.close(); + } + + @Override + public void onChange(List<ResourceChange> changes) { + changesQueue.addAll(changes); + } + + @SuppressWarnings("deprecation") + private void sendOsgiEvent(ResourceChange change) { + Dictionary<String, Object> props = new Hashtable<String, Object>(); + String topic; + switch (change.getType()) { + case ADDED: + topic = SlingConstants.TOPIC_RESOURCE_ADDED; + break; + + case CHANGED: + topic = SlingConstants.TOPIC_RESOURCE_CHANGED; + break; + + case REMOVED: + topic = SlingConstants.TOPIC_RESOURCE_REMOVED; + break; + + default: + return; + } + + props.put(SlingConstants.PROPERTY_PATH, change.getPath()); + if (change.getUserId() != null) { + props.put(SlingConstants.PROPERTY_USERID, change.getUserId()); + } + if (change.getAddedPropertyNames() != null ) { + props.put(SlingConstants.PROPERTY_ADDED_ATTRIBUTES, change.getAddedPropertyNames().toArray(new String[change.getAddedPropertyNames().size()])); + } + if (change.getChangedPropertyNames() != null) { + props.put(SlingConstants.PROPERTY_CHANGED_ATTRIBUTES, change.getChangedPropertyNames().toArray(new String[change.getChangedPropertyNames().size()])); + } + if ( change.getRemovedPropertyNames() != null ) { + props.put(SlingConstants.PROPERTY_REMOVED_ATTRIBUTES, change.getRemovedPropertyNames().toArray(new String[change.getRemovedPropertyNames().size()])); + } + if (change.getType() != ChangeType.REMOVED) { + Resource resource = resolver.getResource(change.getPath()); + if (resource == null) { + resolver.refresh(); + resource = resolver.getResource(change.getPath()); + } + if (resource != null) { + if (resource.getResourceType() != null) { + props.put(SlingConstants.PROPERTY_RESOURCE_TYPE, resource.getResourceType()); + } + if (resource.getResourceSuperType() != null) { + props.put(SlingConstants.PROPERTY_RESOURCE_SUPER_TYPE, resource.getResourceSuperType()); + } + } + } + if (change.isExternal()) { + props.put("event.application", "unknown"); + } + + final Event event = new Event(topic, props); + eventAdmin.sendEvent(event); + } + + private class EventSendingJob implements Runnable { + + private final BlockingQueue<ResourceChange> changes; + + private volatile boolean stop; + + public EventSendingJob(BlockingQueue<ResourceChange> changes) { + this.changes = changes; + } + + @Override + public void run() { + while (!stop) { + ResourceChange change = null; + try { + change = changes.poll(100, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + logger.warn("Interrupted the OSGi runnable", e); + } + if (change == null) { + continue; + } + try { + sendOsgiEvent(change); + } catch (Exception e) { + logger.error("processOsgiEventQueue: Unexpected problem processing resource change {}", change, e); + } + } + } + + public void stop() { + stop = true; + } + } + +} Propchange: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/observation/OsgiObservationBridge.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/observation/OsgiObservationBridge.java ------------------------------------------------------------------------------ svn:keywords = author date id revision rev url Added: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/observation/ResourceChangeListenerWhiteboard.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/observation/ResourceChangeListenerWhiteboard.java?rev=1710993&view=auto ============================================================================== --- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/observation/ResourceChangeListenerWhiteboard.java (added) +++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/observation/ResourceChangeListenerWhiteboard.java Wed Oct 28 11:09:00 2015 @@ -0,0 +1,117 @@ +/* + * 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.sling.resourceresolver.impl.observation; + +import java.util.Hashtable; +import java.util.IdentityHashMap; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.apache.felix.scr.annotations.ReferencePolicy; +import org.apache.felix.scr.annotations.References; +import org.apache.felix.scr.annotations.Service; +import org.apache.sling.api.resource.observation.ResourceChangeListener; +import org.apache.sling.resourceresolver.impl.observation.BasicObserverConfiguration.Builder; +import org.apache.sling.api.resource.LoginException; +import org.apache.sling.api.resource.ResourceResolver; +import org.apache.sling.api.resource.ResourceResolverFactory; +import org.apache.sling.api.resource.observation.ExternalResourceListener; +import org.apache.sling.spi.resource.provider.ObservationReporter; +import org.apache.sling.spi.resource.provider.ObserverConfiguration; +import org.osgi.service.event.Event; +import org.osgi.service.event.EventAdmin; + +@Component(immediate = true) +@Service(ResourceChangeListenerWhiteboard.class) +@References({ + @Reference(name = "ResourceChangeListener", referenceInterface = ResourceChangeListener.class, cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE, policy = ReferencePolicy.DYNAMIC), + @Reference(name = "ResourceResolverFactory", referenceInterface = ResourceResolverFactory.class, cardinality = ReferenceCardinality.OPTIONAL_UNARY, policy = ReferencePolicy.DYNAMIC) }) +public class ResourceChangeListenerWhiteboard { + + public static final String TOPIC_RESOURCE_CHANGE_LISTENER_UPDATE = "org/apache/sling/api/resource/ResourceChangeListener/UPDATE"; + + private Map<ResourceChangeListener, ObserverConfiguration> listeners = new IdentityHashMap<ResourceChangeListener, ObserverConfiguration>(); + + private Map<ResourceChangeListener, Builder> pendingListeners = new IdentityHashMap<ResourceChangeListener, Builder>(); + + private String[] searchPaths; + + @Reference + private EventAdmin eventAdmin; + + public ObservationReporter getObservationReporter() { + return new BasicObservationReporter(listeners); + } + + protected void bindResourceChangeListener(ResourceChangeListener listener, Map<String, Object> properties) { + Builder builder = new Builder(); + builder.setFromProperties(properties); + builder.setIncludeExternal(listener instanceof ExternalResourceListener); + + if (searchPaths == null) { + pendingListeners.put(listener, builder); + } else { + builder.setSearchPaths(searchPaths); + listeners.put(listener, builder.build()); + postListenersChangedEvent(); + } + } + + protected void unbindResourceChangeListener(ResourceChangeListener listener, Map<String, Object> properties) { + if (listeners.remove(listener) != null) { + postListenersChangedEvent(); + } + pendingListeners.remove(listener); + } + + protected void bindResourceResolverFactory(ResourceResolverFactory factory) throws LoginException { + ResourceResolver resolver = factory.getResourceResolver(null); + try { + this.searchPaths = resolver.getSearchPath(); + activatePendingListeners(); + } finally { + resolver.close(); + } + } + + protected void unbindResourceResolverFactory(ResourceResolverFactory factory) { + this.searchPaths = null; + } + + private void activatePendingListeners() { + boolean added = false; + for (Entry<ResourceChangeListener, Builder> e : pendingListeners.entrySet()) { + Builder builder = e.getValue(); + builder.setSearchPaths(searchPaths); + listeners.put(e.getKey(), builder.build()); + added = true; + } + pendingListeners.clear(); + if (added) { + postListenersChangedEvent(); + } + } + + private void postListenersChangedEvent() { + eventAdmin.sendEvent(new Event(TOPIC_RESOURCE_CHANGE_LISTENER_UPDATE, new Hashtable<String, Object>())); + } +} Propchange: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/observation/ResourceChangeListenerWhiteboard.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/observation/ResourceChangeListenerWhiteboard.java ------------------------------------------------------------------------------ svn:keywords = author date id revision rev url Added: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/ProviderContextImpl.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/ProviderContextImpl.java?rev=1710993&view=auto ============================================================================== --- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/ProviderContextImpl.java (added) +++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/ProviderContextImpl.java Wed Oct 28 11:09:00 2015 @@ -0,0 +1,49 @@ +/* + * 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.sling.resourceresolver.impl.providers; + +import java.util.Set; + +import org.apache.sling.spi.resource.provider.ObservationReporter; +import org.apache.sling.spi.resource.provider.ProviderContext; + +/** + * Provider context implementation + */ +public class ProviderContextImpl implements ProviderContext { + + private final ObservationReporter observationReporter; + + private final Set<String> excludedPaths; + + public ProviderContextImpl(final ObservationReporter observationReporter, final Set<String> excludedPaths) { + this.observationReporter = observationReporter; + this.excludedPaths = excludedPaths; + } + + @Override + public ObservationReporter getObservationReporter() { + return observationReporter; + } + + @Override + public Set<String> getExcludedPaths() { + return excludedPaths; + } +} Propchange: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/ProviderContextImpl.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/ProviderContextImpl.java ------------------------------------------------------------------------------ svn:keywords = author date id revision rev url Modified: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderTracker.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderTracker.java?rev=1710993&r1=1710992&r2=1710993&view=diff ============================================================================== --- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderTracker.java (original) +++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderTracker.java Wed Oct 28 11:09:00 2015 @@ -22,10 +22,12 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Dictionary; import java.util.HashMap; +import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import org.apache.felix.scr.annotations.Activate; @@ -34,11 +36,19 @@ import org.apache.felix.scr.annotations. import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.Service; import org.apache.sling.api.SlingConstants; +import org.apache.sling.api.resource.observation.ResourceChange; +import org.apache.sling.api.resource.observation.ResourceChange.ChangeType; +import org.apache.sling.api.resource.observation.ResourceChangeListener; import org.apache.sling.api.resource.runtime.dto.FailureReason; import org.apache.sling.api.resource.runtime.dto.ResourceProviderDTO; import org.apache.sling.api.resource.runtime.dto.ResourceProviderFailureDTO; import org.apache.sling.api.resource.runtime.dto.RuntimeDTO; import org.apache.sling.resourceresolver.impl.legacy.LegacyResourceProviderWhiteboard; +import org.apache.sling.resourceresolver.impl.observation.BasicObservationReporter; +import org.apache.sling.resourceresolver.impl.observation.ResourceChangeListenerWhiteboard; +import org.apache.sling.spi.resource.provider.ObservationReporter; +import org.apache.sling.spi.resource.provider.ObserverConfiguration; +import org.apache.sling.spi.resource.provider.ProviderContext; import org.apache.sling.spi.resource.provider.ResourceProvider; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; @@ -57,6 +67,8 @@ import org.slf4j.LoggerFactory; @Service(value = ResourceProviderTracker.class) public class ResourceProviderTracker { + private static final ObservationReporter EMPTY_REPORTER = new BasicObservationReporter(Collections.<ResourceChangeListener, ObserverConfiguration> emptyMap()); + private final Logger logger = LoggerFactory.getLogger(this.getClass()); private final Map<ServiceReference, ResourceProviderInfo> infos = new ConcurrentHashMap<ServiceReference, ResourceProviderInfo>(); @@ -72,6 +84,11 @@ public class ResourceProviderTracker { @Reference private EventAdmin eventAdmin; + private ObservationReporter reporter = EMPTY_REPORTER; + + @Reference + private ResourceChangeListenerWhiteboard resourceChangeListeners; + private volatile ResourceProviderStorage storage; @Activate @@ -218,11 +235,12 @@ public class ResourceProviderTracker { */ private void deactivate(final ResourceProviderHandler handler) { handler.deactivate(); - postEvent(SlingConstants.TOPIC_RESOURCE_PROVIDER_REMOVED, handler.getInfo()); + postOSGiEvent(SlingConstants.TOPIC_RESOURCE_PROVIDER_REMOVED, handler.getInfo()); + postResourceProviderChange(ChangeType.PROVIDER_REMOVED, handler.getInfo()); logger.debug("Deactivated resource provider {}", handler.getInfo()); } - private void postEvent(final String topic, final ResourceProviderInfo info) { + private void postOSGiEvent(final String topic, final ResourceProviderInfo info) { final Dictionary<String, Object> eventProps = new Hashtable<String, Object>(); eventProps.put(SlingConstants.PROPERTY_PATH, info.getPath()); String pid = (String) info.getServiceReference().getProperty(Constants.SERVICE_PID); @@ -235,6 +253,11 @@ public class ResourceProviderTracker { eventAdmin.postEvent(new Event(topic, eventProps)); } + private void postResourceProviderChange(ChangeType type, final ResourceProviderInfo info) { + ResourceChange change = new ResourceChange(type, info.getPath(), false, null, null, null); + this.reporter.reportChanges(Collections.singletonList(change), false); + } + /** * Activate a resource provider * @param handler The provider handler @@ -246,7 +269,8 @@ public class ResourceProviderTracker { return false; } - postEvent(SlingConstants.TOPIC_RESOURCE_PROVIDER_ADDED, handler.getInfo()); + postOSGiEvent(SlingConstants.TOPIC_RESOURCE_PROVIDER_ADDED, handler.getInfo()); + postResourceProviderChange(ChangeType.PROVIDER_ADDED, handler.getInfo()); logger.debug("Activated resource provider {}", handler.getInfo()); return true; } @@ -312,4 +336,16 @@ public class ResourceProviderTracker { d.serviceId = (Long)info.getServiceReference().getProperty(Constants.SERVICE_ID); d.useResourceAccessSecurity = info.getUseResourceAccessSecurity(); } + + private ProviderContext createProviderContext(final ResourceProviderHandler handler) { + final Set<String> excludedPaths = new HashSet<String>(); + String path = handler.getInfo().getPath(); + for (String providerPath : handlers.keySet()) { + if (providerPath.startsWith(path)) { + excludedPaths.add(providerPath); + } + } + excludedPaths.remove(path); + return new ProviderContextImpl(reporter, excludedPaths); + } } Modified: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/AuthenticatedResourceProvider.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/AuthenticatedResourceProvider.java?rev=1710993&r1=1710992&r2=1710993&view=diff ============================================================================== --- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/AuthenticatedResourceProvider.java (original) +++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/AuthenticatedResourceProvider.java Wed Oct 28 11:09:00 2015 @@ -95,7 +95,12 @@ public class AuthenticatedResourceProvid private Object authenticate() throws LoginException { if (!authenticated && (info.getAuthType() == AuthType.required || info.getAuthType() == AuthType.lazy)) { - contextData = rp.authenticate(authInfo); + try { + contextData = rp.authenticate(authInfo); + } catch ( final LoginException le ) { + logger.debug("Unable to login into resource provider " + rp, le); + throw le; + } authenticated = true; } return contextData; Modified: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/CombinedResourceProvider.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/CombinedResourceProvider.java?rev=1710993&r1=1710992&r2=1710993&view=diff ============================================================================== --- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/CombinedResourceProvider.java (original) +++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/CombinedResourceProvider.java Wed Oct 28 11:09:00 2015 @@ -35,11 +35,15 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; + import org.apache.commons.collections.IteratorUtils; import org.apache.commons.collections.ListUtils; import org.apache.commons.collections.Transformer; import org.apache.commons.lang.ArrayUtils; import org.apache.sling.api.SlingException; +import org.apache.sling.api.resource.LoginException; import org.apache.sling.api.resource.PersistenceException; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ResourceResolver; @@ -66,15 +70,15 @@ public class CombinedResourceProvider { private static final Logger logger = LoggerFactory.getLogger(CombinedResourceProvider.class); - private static final StatefulResourceProvider EMPTY_PROVIDER = new EmptyResourceProvider(); - private final ResourceProviderStorage storage; private final ResourceResolver resolver; private final ResourceProviderAuthenticator authenticator; - public CombinedResourceProvider(ResourceProviderStorage storage, ResourceResolver resolver, ResourceProviderAuthenticator authenticator) { + public CombinedResourceProvider(ResourceProviderStorage storage, + ResourceResolver resolver, + ResourceProviderAuthenticator authenticator) { this.storage = storage; this.resolver = resolver; this.authenticator = authenticator; @@ -93,7 +97,8 @@ public class CombinedResourceProvider { * Refreshes all providers. */ public void refresh() { - for (StatefulResourceProvider p : authenticator.getAll(storage.getRefreshableHandlers(), this)) { + for (StatefulResourceProvider p : authenticator.getAllUsed()) { + // TODO check for refreshable p.refresh(); } } @@ -120,14 +125,18 @@ public class CombinedResourceProvider { */ public Resource getParent(Resource child) { final String path = child.getPath(); - final StatefulResourceProvider provider = getBestMatchingProvider(path); - Resource parentCandidate = provider.getParent(child); - if (parentCandidate != null) { - return parentCandidate; - } - String parentPath = ResourceUtil.getParent(path); - if (parentPath != null && isIntermediatePath(parentPath)) { - return new SyntheticResource(resolver, parentPath, ResourceProvider.RESOURCE_TYPE_SYNTHETIC); + try { + final StatefulResourceProvider provider = getBestMatchingProvider(path); + Resource parentCandidate = provider.getParent(child); + if (parentCandidate != null) { + return parentCandidate; + } + String parentPath = ResourceUtil.getParent(path); + if (parentPath != null && isIntermediatePath(parentPath)) { + return new SyntheticResource(resolver, parentPath, ResourceProvider.RESOURCE_TYPE_SYNTHETIC); + } + } catch ( final LoginException le ) { + // ignore, we just return null } return null; } @@ -193,26 +202,31 @@ public class CombinedResourceProvider { */ @SuppressWarnings("unchecked") public Iterator<Resource> listChildren(final Resource parent) { - List<StatefulResourceProvider> matching = getMatchingProviders(parent.getPath()); - Iterator<Resource> realChildren = head(matching).listChildren(parent); - Iterator<Resource> syntheticChildren = getSyntheticChildren(parent).iterator(); - Iterator<Resource> allChildren; - if (realChildren == null) { - allChildren = syntheticChildren; - } else { - allChildren = new UniqueIterator(chainedIterator(realChildren, syntheticChildren)); - } - return transformedIterator(allChildren, new Transformer() { - @Override - public Object transform(Object input) { - Resource resource = (Resource) input; - resource.getResourceMetadata().setResolutionPath(resource.getPath()); - return resource; + try { + List<StatefulResourceProvider> matching = getMatchingProviders(parent.getPath()); + Iterator<Resource> realChildren = head(matching).listChildren(parent); + Iterator<Resource> syntheticChildren = getSyntheticChildren(parent).iterator(); + Iterator<Resource> allChildren; + if (realChildren == null) { + allChildren = syntheticChildren; + } else { + allChildren = new UniqueIterator(chainedIterator(realChildren, syntheticChildren)); } - }); + return transformedIterator(allChildren, new Transformer() { + @Override + public Object transform(Object input) { + Resource resource = (Resource) input; + resource.getResourceMetadata().setResolutionPath(resource.getPath()); + return resource; + } + }); + } catch ( final LoginException le ) { + // ignore + } + return null; } - private List<Resource> getSyntheticChildren(Resource parent) { + private List<Resource> getSyntheticChildren(Resource parent) throws LoginException { Node<ResourceProviderHandler> node = storage.getTree().getNode(parent.getPath()); if (node == null) { return Collections.emptyList(); @@ -240,12 +254,17 @@ public class CombinedResourceProvider { */ public Collection<String> getAttributeNames() { final Set<String> names = new LinkedHashSet<String>(); + try { for (StatefulResourceProvider p : authenticator.getAll(storage.getAttributableHandlers(), this)) { Collection<String> newNames = p.getAttributeNames(); if (newNames != null) { names.addAll(newNames); } } + } catch (LoginException le) { + // TODO - ignore for a single handler + throw new SlingException("Unable to authenticate", le); + } return names; } @@ -255,12 +274,17 @@ public class CombinedResourceProvider { * the providers. */ public Object getAttribute(String name) { + try { for (StatefulResourceProvider p : authenticator.getAll(storage.getAttributableHandlers(), this)) { Object attribute = p.getAttribute(name); if (attribute != null) { return attribute; } } + } catch (LoginException le) { + // TODO - ignore for a single handler + throw new SlingException("Unable to authenticate", le); + } return null; } @@ -276,6 +300,7 @@ public class CombinedResourceProvider { * @return The new resource */ public Resource create(String path, Map<String, Object> properties) throws PersistenceException { + try { List<StatefulResourceProvider> matching = getMatchingModifiableProviders(path); Resource creationResultResource = head(matching).create(path, properties); if (creationResultResource != null) { @@ -284,6 +309,10 @@ public class CombinedResourceProvider { // If none of the viable handlers could create the resource or if the // list of handlers was empty, throw an Exception throw new UnsupportedOperationException("create '" + getName(path) + "' at " + ResourceUtil.getParent(path)); + } catch (LoginException le) { + // TODO - ignore throw PersistenceException + throw new SlingException("Unable to authenticate", le); + } } /** @@ -298,6 +327,7 @@ public class CombinedResourceProvider { * If deletion fails */ public void delete(Resource resource) throws PersistenceException { + try { final String path = resource.getPath(); final Map<String, String> parameters = resource.getResourceMetadata().getParameterMap(); boolean anyProviderAttempted = false; @@ -315,6 +345,10 @@ public class CombinedResourceProvider { if (!anyProviderAttempted) { throw new UnsupportedOperationException("delete at '" + path + "'"); } + } catch (LoginException le) { + // TODO - ignore for a single handler + throw new SlingException("Unable to authenticate", le); + } } /** @@ -358,11 +392,16 @@ public class CombinedResourceProvider { * Return the union of query languages supported by the providers. */ public String[] getSupportedLanguages() { + try { Set<String> supportedLanguages = new LinkedHashSet<String>(); for (StatefulResourceProvider p : authenticator.getAll(storage.getJcrQuerableHandlers(), this)) { supportedLanguages.addAll(Arrays.asList(p.getSupportedLanguages())); } return supportedLanguages.toArray(new String[supportedLanguages.size()]); + } catch (LoginException le) { + // TODO - ignore for a single handler + throw new SlingException("Unable to authenticate", le); + } } /** @@ -378,6 +417,7 @@ public class CombinedResourceProvider { } private List<StatefulResourceProvider> getQuerableProviders(String language) { + try { List<StatefulResourceProvider> querableProviders = new ArrayList<StatefulResourceProvider>(); for (StatefulResourceProvider p : authenticator.getAll(storage.getJcrQuerableHandlers(), this)) { if (ArrayUtils.contains(p.getSupportedLanguages(), language)) { @@ -385,6 +425,10 @@ public class CombinedResourceProvider { } } return querableProviders; + } catch (LoginException le) { + // TODO - ignore for a single handler + throw new SlingException("Unable to authenticate", le); + } } /** @@ -405,6 +449,7 @@ public class CombinedResourceProvider { */ @SuppressWarnings("unchecked") public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) { + try { for (StatefulResourceProvider p : authenticator.getAll(storage.getAdaptableHandlers(), this)) { final Object adaptee = p.adaptTo(type); if (adaptee != null) { @@ -412,6 +457,10 @@ public class CombinedResourceProvider { } } return null; + } catch (LoginException le) { + // TODO - ignore for a single handler + throw new SlingException("Unable to authenticate", le); + } } /** @@ -420,11 +469,16 @@ public class CombinedResourceProvider { * Returns false if there's no such provider. */ public boolean copy(String srcAbsPath, String destAbsPath) throws PersistenceException { + try { List<StatefulResourceProvider> srcProviders = getMatchingProviders(srcAbsPath); List<StatefulResourceProvider> dstProviders = getMatchingModifiableProviders(destAbsPath); @SuppressWarnings("unchecked") List<StatefulResourceProvider> intersection = ListUtils.intersection(srcProviders, dstProviders); return head(intersection).copy(srcAbsPath, destAbsPath); + } catch (LoginException le) { + // TODO - ignore for a single handler + throw new SlingException("Unable to authenticate", le); + } } /** @@ -433,18 +487,24 @@ public class CombinedResourceProvider { * Returns false if there's no such provider. */ public boolean move(String srcAbsPath, String destAbsPath) throws PersistenceException { + try { List<StatefulResourceProvider> srcProviders = getMatchingModifiableProviders(srcAbsPath); List<StatefulResourceProvider> dstProviders = getMatchingModifiableProviders(destAbsPath); @SuppressWarnings("unchecked") List<StatefulResourceProvider> intersection = ListUtils.intersection(srcProviders, dstProviders); return head(intersection).move(srcAbsPath, destAbsPath); + } catch (LoginException le) { + // TODO - ignore for a single handler + throw new SlingException("Unable to authenticate", le); + } } public ResourceProviderStorage getResourceProviderStorage() { return this.storage; } - public StatefulResourceProvider getStatefulResourceProvider(final ResourceProviderHandler handler) { + public @CheckForNull StatefulResourceProvider getStatefulResourceProvider(@Nonnull final ResourceProviderHandler handler) + throws LoginException { if ( handler != null ) { return authenticator.getStateful(handler, this); } @@ -456,12 +516,12 @@ public class CombinedResourceProvider { * @return * @throws SlingException */ - private StatefulResourceProvider getBestMatchingProvider(final String path) { + private StatefulResourceProvider getBestMatchingProvider(final String path) throws LoginException { final ResourceProviderHandler handler = storage.getTree().getBestMatchingNode(path); return handler == null ? EmptyResourceProvider.SINGLETON : authenticator.getStateful(handler, this); } - private List<StatefulResourceProvider> getMatchingProviders(String path) { + private List<StatefulResourceProvider> getMatchingProviders(String path) throws LoginException { List<ResourceProviderHandler> handlers = storage.getTree().getMatchingNodes(path); StatefulResourceProvider[] matching = new StatefulResourceProvider[handlers.size()]; int i = matching.length - 1; @@ -471,7 +531,7 @@ public class CombinedResourceProvider { return Arrays.asList(matching); } - private List<StatefulResourceProvider> getMatchingModifiableProviders(String path) { + private List<StatefulResourceProvider> getMatchingModifiableProviders(String path) throws LoginException { List<ResourceProviderHandler> handlers = storage.getTree().getMatchingNodes(path); List<StatefulResourceProvider> matching = new ArrayList<StatefulResourceProvider>(handlers.size()); for (ResourceProviderHandler h : handlers) { @@ -485,20 +545,12 @@ public class CombinedResourceProvider { private static StatefulResourceProvider head(List<StatefulResourceProvider> list) { if (list.isEmpty()) { - return EMPTY_PROVIDER; + return EmptyResourceProvider.SINGLETON; } else { return list.get(0); } } - private static <T> List<T> tail(List<T> list) { - if (list.isEmpty()) { - return Collections.emptyList(); - } else { - return list.subList(1, list.size()); - } - } - private class CombinedQueryResult extends QueryResult implements Iterable<Resource> { private final Query q; @@ -517,6 +569,7 @@ public class CombinedResourceProvider { @Override public Iterator<Resource> iterator() { + try { @SuppressWarnings("unchecked") Iterator<Iterator<Resource>> iterators = IteratorUtils.transformedIterator(authenticator.getAll(storage.getNativeQuerableHandlers(), CombinedResourceProvider.this).iterator(), new Transformer() { @@ -527,6 +580,10 @@ public class CombinedResourceProvider { } }); return new ChainedIterator<Resource>(iterators); + } catch (LoginException le) { + // TODO - ignore for a single handler + throw new SlingException("Unable to authenticate", le); + } } } Modified: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/ResourceProviderAuthenticator.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/ResourceProviderAuthenticator.java?rev=1710993&r1=1710992&r2=1710993&view=diff ============================================================================== --- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/ResourceProviderAuthenticator.java (original) +++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/ResourceProviderAuthenticator.java Wed Oct 28 11:09:00 2015 @@ -24,7 +24,8 @@ import java.util.IdentityHashMap; import java.util.List; import java.util.Map; -import org.apache.sling.api.SlingException; +import javax.annotation.Nonnull; + import org.apache.sling.api.resource.LoginException; import org.apache.sling.api.resource.ResourceResolver; import org.apache.sling.api.resource.runtime.dto.AuthType; @@ -73,9 +74,6 @@ public class ResourceProviderAuthenticat StatefulResourceProvider rp = stateful.get(handler); if (rp == null) { rp = createStateful(handler, combinedProvider); - if (rp == null) { - return null; - } stateful.put(handler, rp); if (handler.getInfo().getAuthType() != AuthType.no) { authenticated.add(rp); @@ -87,12 +85,13 @@ public class ResourceProviderAuthenticat return rp; } - public StatefulResourceProvider getStateful(ResourceProviderHandler handler, CombinedResourceProvider combinedProvider) { - try { - return authenticate(handler, combinedProvider); - } catch (LoginException e) { - throw new SlingException("Can't authenticate provider", e); - } + public Collection<StatefulResourceProvider> getAllUsed() { + return stateful.values(); + } + + public StatefulResourceProvider getStateful(ResourceProviderHandler handler, CombinedResourceProvider combinedProvider) + throws LoginException { + return authenticate(handler, combinedProvider); } public Collection<StatefulResourceProvider> getAllUsedAuthenticated() { @@ -104,7 +103,7 @@ public class ResourceProviderAuthenticat } public Collection<StatefulResourceProvider> getAll(List<ResourceProviderHandler> handlers, - CombinedResourceProvider combinedProvider) { + CombinedResourceProvider combinedProvider) throws LoginException { List<StatefulResourceProvider> result = new ArrayList<StatefulResourceProvider>(handlers.size()); for (ResourceProviderHandler h : handlers) { result.add(getStateful(h, combinedProvider)); @@ -112,13 +111,9 @@ public class ResourceProviderAuthenticat return result; } - private StatefulResourceProvider createStateful(ResourceProviderHandler handler, + private @Nonnull StatefulResourceProvider createStateful(ResourceProviderHandler handler, CombinedResourceProvider combinedProvider) throws LoginException { - ResourceProvider<?> rp = handler.getResourceProvider(); - if (rp == null) { - logger.warn("Empty resource provider for {}", handler); - return null; - } + final ResourceProvider<?> rp = handler.getResourceProvider(); StatefulResourceProvider authenticated; authenticated = new AuthenticatedResourceProvider(rp, handler.getInfo(), resolver, authInfo, combinedProvider); if (handler.getInfo().getUseResourceAccessSecurity()) {