/** * Copyright (c) 2012 Cloudsmith Inc. and other contributors, as listed below. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Cloudsmith * */ package org.cloudsmith.xtext.resource; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.resource.Resource; import com.google.common.base.Preconditions; import com.google.inject.Provider; import com.google.inject.Singleton; /** * <p> * A {@code ResourceAccessScope} acts as a provider of {@link ResourceAccess} returning an instance that has been bound to the current {@link Thread}, * or a default "unspecific" ResourceAccess if the ResourceAccessScope has not been entered. * </p> * <p> * This works similar to how a Guice Scope works, but this implementation is NOT a guice scope. * </p> * <p> * When entering, care must be taken to exit the scope in a finally-clause or the result may be memory leaks * </p> * */ @Singleton public class ResourceAccessScope implements Provider<ResourceAccess> { private final ThreadLocal<ResourceAccess> context; private static final ResourceAccess unspecific = new ResourceAccess(null); public ResourceAccessScope() { this.context = new ThreadLocal<ResourceAccess>(); } /** * Enters a resource specific scope. The given {@code} resource may not be null, and the resource * must have an URI set. * * @param resource * the Resource to enter */ public void enter(Resource resource) { Preconditions.checkNotNull(resource, "resource"); URI uri = resource.getURI(); Preconditions.checkArgument(uri != null, "Resource.getURI() can not be null."); enter(uri); } /** * Enters a resource specific scope. * * @throws IllegalStateException * if the scope is already entered. * @param uri */ public void enter(URI uri) { Preconditions.checkNotNull(uri, "uri"); if(this.context.get() != null) throw new IllegalStateException("ResourceAccessScope already entered!"); this.context.set(new ResourceAccess(uri)); } public void exit() { if(this.context.get() == null) throw new IllegalStateException("ResourceAccessScope was not entered!"); context.remove(); } @Override public ResourceAccess get() { ResourceAccess ra = context.get(); return ra == null ? unspecific : ra; } }