/*
* ModeShape (http://www.modeshape.org)
*
* Licensed 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.modeshape.jcr;
import java.math.BigDecimal;
import java.security.AccessController;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.modeshape.common.annotation.Immutable;
import org.modeshape.common.logging.Logger;
import org.modeshape.common.text.TextDecoder;
import org.modeshape.common.text.TextEncoder;
import org.modeshape.common.util.CheckArg;
import org.modeshape.common.util.SecureHash;
import org.modeshape.common.util.ThreadPoolFactory;
import org.modeshape.common.util.ThreadPools;
import org.modeshape.jcr.query.model.TypeSystem;
import org.modeshape.jcr.security.SecurityContext;
import org.modeshape.jcr.value.BinaryFactory;
import org.modeshape.jcr.value.DateTimeFactory;
import org.modeshape.jcr.value.NameFactory;
import org.modeshape.jcr.value.NamespaceRegistry;
import org.modeshape.jcr.value.PathFactory;
import org.modeshape.jcr.value.Property;
import org.modeshape.jcr.value.PropertyFactory;
import org.modeshape.jcr.value.PropertyType;
import org.modeshape.jcr.value.ReferenceFactory;
import org.modeshape.jcr.value.StringFactory;
import org.modeshape.jcr.value.UriFactory;
import org.modeshape.jcr.value.ValueFactories;
import org.modeshape.jcr.value.ValueFactory;
import org.modeshape.jcr.value.ValueTypeSystem;
import org.modeshape.jcr.value.basic.BasicPropertyFactory;
import org.modeshape.jcr.value.basic.BooleanValueFactory;
import org.modeshape.jcr.value.basic.DecimalValueFactory;
import org.modeshape.jcr.value.basic.DoubleValueFactory;
import org.modeshape.jcr.value.basic.JodaDateTimeValueFactory;
import org.modeshape.jcr.value.basic.LongValueFactory;
import org.modeshape.jcr.value.basic.NameValueFactory;
import org.modeshape.jcr.value.basic.ObjectValueFactory;
import org.modeshape.jcr.value.basic.PathValueFactory;
import org.modeshape.jcr.value.basic.ReferenceValueFactory;
import org.modeshape.jcr.value.basic.SimpleNamespaceRegistry;
import org.modeshape.jcr.value.basic.StringValueFactory;
import org.modeshape.jcr.value.basic.ThreadSafeNamespaceRegistry;
import org.modeshape.jcr.value.basic.UriValueFactory;
import org.modeshape.jcr.value.binary.BinaryStore;
import org.modeshape.jcr.value.binary.BinaryStoreValueFactory;
import org.modeshape.jcr.value.binary.TransientBinaryStore;
/**
* An ExecutionContext is a representation of the environment or context in which a component or operation is operating. Some
* components require this context to be passed into individual methods, allowing the context to vary with each method invocation.
* Other components require the context to be provided before it's used, and will use that context for all its operations (until
* it is given a different one).
* <p>
* ExecutionContext instances are {@link Immutable immutable}, so components may hold onto references to them without concern of
* those contexts changing. Contexts may be used to create other contexts that vary the environment and/or security context. For
* example, an ExecutionContext could be used to create another context that references the same {@link #getNamespaceRegistry()
* namespace registry} but which has a different {@link #getSecurityContext() security context}.
* </p>
*/
@Immutable
public final class ExecutionContext implements ThreadPoolFactory, Cloneable, NamespaceRegistry.Holder {
public static final ExecutionContext DEFAULT_CONTEXT = new ExecutionContext();
private final ThreadPoolFactory threadPools;
private final PropertyFactory propertyFactory;
private final ValueFactories valueFactories;
private final NamespaceRegistry namespaceRegistry;
private final SecurityContext securityContext;
private final BinaryStore binaryStore;
/** The unique ID string, which is always generated so that it can be final and not volatile. */
private final String id = SecureHash.sha1(UUID.randomUUID().toString()).substring(0, 9);
private final String processId;
private final Map<String, String> data;
// This class is implemented with separate members for each factory so that the typical usage is optimized.
private final TextDecoder decoder;
private final TextEncoder encoder;
private final StringFactory stringFactory;
private final BinaryFactory binaryFactory;
private final ValueFactory<Boolean> booleanFactory;
private final DateTimeFactory dateFactory;
private final ValueFactory<BigDecimal> decimalFactory;
private final ValueFactory<Double> doubleFactory;
private final ValueFactory<Long> longFactory;
private final NameFactory nameFactory;
private final PathFactory pathFactory;
private final ReferenceFactory referenceFactory;
private final ReferenceFactory weakReferenceFactory;
private final ReferenceFactory simpleReferenceFactory;
private final UriFactory uriFactory;
private final ValueFactory<Object> objectFactory;
private final TypeSystem typeSystem;
/**
* Create an instance of an execution context that uses the {@link AccessController#getContext() current JAAS calling context}
* , with default implementations for all other components (including default namespaces in the
* {@link #getNamespaceRegistry() namespace registry}.
*/
@SuppressWarnings( "synthetic-access" )
public ExecutionContext() {
this(new NullSecurityContext(), null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null);
initializeDefaultNamespaces(this.getNamespaceRegistry());
assert securityContext != null;
}
protected ExecutionContext( ExecutionContext context ) {
this(context.securityContext, context.namespaceRegistry, context.propertyFactory, context.threadPools,
context.binaryStore, context.data, context.processId, context.decoder, context.encoder, context.stringFactory,
context.binaryFactory, context.booleanFactory, context.dateFactory, context.decimalFactory, context.doubleFactory,
context.longFactory, context.nameFactory, context.pathFactory, context.referenceFactory,
context.weakReferenceFactory, context.simpleReferenceFactory, context.uriFactory, context.objectFactory);
}
/**
* Create an instance of the execution context by supplying all parameters.
*
* @param securityContext the security context, or null if there is no associated authenticated user
* @param namespaceRegistry the namespace registry implementation, or null if a thread-safe version of
* {@link org.modeshape.jcr.value.basic.SimpleNamespaceRegistry} instance should be used
* @param propertyFactory the {@link org.modeshape.jcr.value.PropertyFactory} implementation, or null if a {@link org.modeshape.jcr.value.basic.BasicPropertyFactory} instance
* should be used
* @param threadPoolFactory the {@link org.modeshape.common.util.ThreadPoolFactory} implementation, or null if a {@link org.modeshape.common.util.ThreadPools} instance should be
* used
* @param binaryStore the {@link org.modeshape.jcr.value.binary.BinaryStore} implementation, or null if a default {@link org.modeshape.jcr.value.binary.TransientBinaryStore} should be used
* @param data the custom data for this context, or null if there is no such data
* @param processId the unique identifier of the process in which this context exists, or null if it should be generated
* @param decoder the decoder that should be used; if null, the {@link org.modeshape.jcr.value.ValueFactory#DEFAULT_DECODER default decoder} is used.
* @param encoder the encoder that should be used; if null, the {@link org.modeshape.jcr.value.ValueFactory#DEFAULT_ENCODER default encoder} is used.
* @param stringFactory the string factory that should be used; if null, a default implementation will be used
* @param binaryFactory the binary factory that should be used; if null, a default implementation will be used
* @param booleanFactory the boolean factory that should be used; if null, a default implementation will be used
* @param dateFactory the date factory that should be used; if null, a default implementation will be used
* @param decimalFactory the decimal factory that should be used; if null, a default implementation will be used
* @param doubleFactory the double factory that should be used; if null, a default implementation will be used
* @param longFactory the long factory that should be used; if null, a default implementation will be used
* @param nameFactory the name factory that should be used; if null, a default implementation will be used
* @param pathFactory the path factory that should be used; if null, a default implementation will be used
* @param referenceFactory the strong reference factory that should be used; if null, a default implementation will be used
* @param weakReferenceFactory the weak reference factory that should be used; if null, a default implementation will be used
* @param simpleReferenceFactory the simple reference factory that should be used; if null, a default implementation will be used
* @param uriFactory the URI factory that should be used; if null, a default implementation will be used
* @param objectFactory the object factory that should be used; if null, a default implementation will be used
*/
protected ExecutionContext( SecurityContext securityContext,
NamespaceRegistry namespaceRegistry,
PropertyFactory propertyFactory,
ThreadPoolFactory threadPoolFactory,
BinaryStore binaryStore,
Map<String, String> data,
String processId,
TextDecoder decoder,
TextEncoder encoder,
StringFactory stringFactory,
BinaryFactory binaryFactory,
ValueFactory<Boolean> booleanFactory,
DateTimeFactory dateFactory,
ValueFactory<BigDecimal> decimalFactory,
ValueFactory<Double> doubleFactory,
ValueFactory<Long> longFactory,
NameFactory nameFactory,
PathFactory pathFactory,
ReferenceFactory referenceFactory,
ReferenceFactory weakReferenceFactory,
ReferenceFactory simpleReferenceFactory,
UriFactory uriFactory,
ValueFactory<Object> objectFactory ) {
assert securityContext != null;
this.securityContext = securityContext;
if (binaryStore == null) binaryStore = TransientBinaryStore.get();
if (namespaceRegistry == null) namespaceRegistry = new ThreadSafeNamespaceRegistry(new SimpleNamespaceRegistry());
if (threadPoolFactory == null) threadPoolFactory = new ThreadPools();
if (data == null) data = Collections.<String, String>emptyMap();
if (processId == null) processId = UUID.randomUUID().toString();
if (decoder == null) decoder = ValueFactory.DEFAULT_DECODER;
if (encoder == null) encoder = ValueFactory.DEFAULT_ENCODER;
// First assign the non-factory members ...
this.binaryStore = binaryStore;
this.namespaceRegistry = namespaceRegistry;
this.threadPools = threadPoolFactory;
this.data = data;
this.processId = processId;
this.decoder = decoder;
this.encoder = encoder;
this.valueFactories = new ContextFactories();
// Create default factories if needed, or obtain new instances that use our ValueFactories (and
// NamespaceRegistry.Holder) instances ...
if (stringFactory == null) {
stringFactory = new StringValueFactory(this, decoder, encoder);
} else {
stringFactory = stringFactory.with(valueFactories).with(this);
}
if (binaryFactory == null) {
// The binary factory should NOT use the string factory that converts namespaces to prefixes ...
StringValueFactory stringFactoryWithoutNamespaces = new StringValueFactory(decoder, encoder);
binaryFactory = new BinaryStoreValueFactory(this.binaryStore, decoder, valueFactories, stringFactoryWithoutNamespaces);
} else {
binaryFactory = binaryFactory.with(binaryStore).with(valueFactories);
}
if (booleanFactory == null) {
booleanFactory = new BooleanValueFactory(decoder, valueFactories);
} else {
booleanFactory = booleanFactory.with(valueFactories);
}
if (dateFactory == null) {
dateFactory = new JodaDateTimeValueFactory(decoder, valueFactories);
} else {
dateFactory = dateFactory.with(valueFactories);
}
if (decimalFactory == null) {
decimalFactory = new DecimalValueFactory(decoder, valueFactories);
} else {
decimalFactory = decimalFactory.with(valueFactories);
}
if (doubleFactory == null) {
doubleFactory = new DoubleValueFactory(decoder, valueFactories);
} else {
doubleFactory = doubleFactory.with(valueFactories);
}
if (longFactory == null) {
longFactory = new LongValueFactory(decoder, valueFactories);
} else {
longFactory = longFactory.with(valueFactories);
}
if (nameFactory == null) {
nameFactory = new NameValueFactory(this, decoder, valueFactories);
} else {
nameFactory = nameFactory.with(valueFactories).with(this);
}
if (pathFactory == null) {
pathFactory = new PathValueFactory(decoder, valueFactories);
} else {
pathFactory = pathFactory.with(valueFactories);
}
if (referenceFactory == null) {
referenceFactory = ReferenceValueFactory.newInstance(decoder, valueFactories, false, false);
} else {
referenceFactory = referenceFactory.with(valueFactories);
}
if (weakReferenceFactory == null) {
weakReferenceFactory = ReferenceValueFactory.newInstance(decoder, valueFactories, true, false);
} else {
weakReferenceFactory = weakReferenceFactory.with(valueFactories);
}
if (simpleReferenceFactory == null) {
simpleReferenceFactory = ReferenceValueFactory.newInstance(decoder, valueFactories, true, true);
} else {
simpleReferenceFactory = simpleReferenceFactory.with(valueFactories);
}
if (uriFactory == null) {
uriFactory = new UriValueFactory(this, decoder, valueFactories);
} else {
uriFactory = uriFactory.with(valueFactories).with(this);
}
if (objectFactory == null) {
objectFactory = new ObjectValueFactory(decoder, valueFactories);
} else {
objectFactory = objectFactory.with(valueFactories);
}
// Now assign the factory members ...
this.stringFactory = stringFactory;
this.binaryFactory = binaryFactory;
this.booleanFactory = booleanFactory;
this.dateFactory = dateFactory;
this.decimalFactory = decimalFactory;
this.doubleFactory = doubleFactory;
this.longFactory = longFactory;
this.nameFactory = nameFactory;
this.pathFactory = pathFactory;
this.referenceFactory = referenceFactory;
this.weakReferenceFactory = weakReferenceFactory;
this.simpleReferenceFactory = simpleReferenceFactory;
this.uriFactory = uriFactory;
this.objectFactory = objectFactory;
// Assign the things that depend on a ValueFactories implementation ...
this.typeSystem = new ValueTypeSystem(valueFactories);
this.propertyFactory = propertyFactory == null ? new BasicPropertyFactory(valueFactories) : propertyFactory;
}
protected ThreadPoolFactory getThreadPoolFactory() {
return threadPools;
}
/**
* Return a logger associated with this context. This logger records only those activities within the context and provide a
* way to capture the context-specific activities. All log messages are also sent to the system logger, so classes that log
* via this mechanism should <i>not</i> also {@link Logger#getLogger(Class) obtain a system logger}.
*
* @param clazz the class that is doing the logging
* @return the logger, named after <code>clazz</code>; never null
* @see #getLogger(String)
*/
public Logger getLogger( Class<?> clazz ) {
return Logger.getLogger(clazz);
}
/**
* Return a logger associated with this context. This logger records only those activities within the context and provide a
* way to capture the context-specific activities. All log messages are also sent to the system logger, so classes that log
* via this mechanism should <i>not</i> also {@link Logger#getLogger(Class) obtain a system logger}.
*
* @param name the name for the logger
* @return the logger, named after <code>clazz</code>; never null
* @see #getLogger(Class)
*/
public Logger getLogger( String name ) {
return Logger.getLogger(name);
}
/**
* Get the {@link SecurityContext security context} for this context.
*
* @return the security context; never <code>null</code>
*/
public SecurityContext getSecurityContext() {
return securityContext;
}
/**
* Get the (mutable) namespace registry for this context.
*
* @return the namespace registry; never <code>null</code>
*/
@Override
public NamespaceRegistry getNamespaceRegistry() {
return namespaceRegistry;
}
/**
* Get the factory for creating {@link Property} objects.
*
* @return the property factory; never <code>null</code>
*/
public final PropertyFactory getPropertyFactory() {
return propertyFactory;
}
/**
* Get the factories that should be used to create values for {@link Property properties}.
*
* @return the property value factory; never null
*/
public ValueFactories getValueFactories() {
return valueFactories;
}
/**
* Get the binary store that should be used to store binary values. This store is used by the {@link BinaryFactory} in the
* {@link #getValueFactories()}.
*
* @return the binary store; never null
*/
public BinaryStore getBinaryStore() {
return binaryStore;
}
@Override
public ExecutorService getThreadPool( String name ) {
return this.threadPools.getThreadPool(name);
}
@Override
public void releaseThreadPool( ExecutorService pool ) {
this.threadPools.releaseThreadPool(pool);
}
@Override
public ExecutorService getCachedTreadPool( String name ) {
return this.threadPools.getCachedTreadPool(name);
}
@Override
public ScheduledExecutorService getScheduledThreadPool( String name ) {
return this.threadPools.getScheduledThreadPool(name);
}
@Override
public void terminateAllPools( long maxWaitTime,
TimeUnit timeUnit ) {
this.threadPools.terminateAllPools(maxWaitTime, timeUnit);
}
/**
* Get the unique identifier for this context. Each context will always have a unique identifier.
*
* @return the unique identifier string; never null and never empty
*/
public String getId() {
return id;
}
/**
* Get the identifier for the process in which this context exists. Multiple contexts running in the same "process" will all
* have the same identifier.
*
* @return the identifier for the process; never null and never empty
*/
public String getProcessId() {
return processId;
}
/**
* Get the immutable map of custom data that is affiliated with this context.
*
* @return the custom data; never null but possibly empty
*/
public Map<String, String> getData() {
return Collections.unmodifiableMap(data);
}
/**
* Get the text decoder for this context.
*
* @return the decoder; never null
*/
public TextDecoder getDecoder() {
return decoder;
}
/**
* Create a new execution context that mirrors this context but that uses the supplied binary store.
*
* @param binaryStore the binary store that should be used, or null if the default implementation should be used
* @return the execution context that is identical with this execution context, but which uses the supplied binary store;
* never null
*/
public ExecutionContext with( BinaryStore binaryStore ) {
return new ExecutionContext(securityContext, namespaceRegistry, propertyFactory, threadPools, binaryStore, data,
processId, decoder, encoder, stringFactory, binaryFactory, booleanFactory, dateFactory,
decimalFactory, doubleFactory, longFactory, nameFactory, pathFactory, referenceFactory,
weakReferenceFactory, simpleReferenceFactory, uriFactory, objectFactory);
}
/**
* Create a new execution context that mirrors this context but that uses the supplied namespace registry. The resulting
* context's {@link #getValueFactories() value factories} and {@link #getPropertyFactory() property factory} all make use of
* the new namespace registry.
*
* @param namespaceRegistry the new namespace registry implementation, or null if the default implementation should be used
* @return the execution context that is identical with this execution context, but which uses the supplied registry; never
* null
*/
public ExecutionContext with( NamespaceRegistry namespaceRegistry ) {
return new ExecutionContext(securityContext, namespaceRegistry, propertyFactory, threadPools, binaryStore, data,
processId, decoder, encoder, stringFactory, binaryFactory, booleanFactory, dateFactory,
decimalFactory, doubleFactory, longFactory, nameFactory, pathFactory, referenceFactory,
weakReferenceFactory, simpleReferenceFactory, uriFactory, objectFactory);
}
/**
* Create a new execution context that mirrors this context but that uses the supplied {@link ThreadPoolFactory thread pool
* factory}.
*
* @param threadPoolFactory the new thread pool factory implementation, or null if the default implementation should be used
* @return the execution context that is identical with this execution context, but which uses the supplied thread pool
* factory implementation; never null
*/
public ExecutionContext with( ThreadPoolFactory threadPoolFactory ) {
return new ExecutionContext(securityContext, namespaceRegistry, propertyFactory, threadPoolFactory, binaryStore, data,
processId, decoder, encoder, stringFactory, binaryFactory, booleanFactory, dateFactory,
decimalFactory, doubleFactory, longFactory, nameFactory, pathFactory, referenceFactory,
weakReferenceFactory, simpleReferenceFactory, uriFactory, objectFactory);
}
/**
* Create a new execution context that mirrors this context but that uses the supplied {@link PropertyFactory factory}.
*
* @param propertyFactory the new propertyfactory implementation, or null if the default implementation should be used
* @return the execution context that is identical with this execution context, but which uses the supplied property factory
* implementation; never null
*/
public ExecutionContext with( PropertyFactory propertyFactory ) {
return new ExecutionContext(securityContext, namespaceRegistry, propertyFactory, threadPools, binaryStore, data,
processId, decoder, encoder, stringFactory, binaryFactory, booleanFactory, dateFactory,
decimalFactory, doubleFactory, longFactory, nameFactory, pathFactory, referenceFactory,
weakReferenceFactory, simpleReferenceFactory, uriFactory, objectFactory);
}
/**
* Create an {@link ExecutionContext} that is the same as this context, but which uses the supplied {@link SecurityContext
* security context}.
*
* @param securityContext the new security context to use; may be null
* @return the execution context that is identical with this execution context, but with a different security context; never
* null
* @throws IllegalArgumentException if the <code>name</code> is null
*/
public ExecutionContext with( SecurityContext securityContext ) {
return new ExecutionContext(securityContext, namespaceRegistry, propertyFactory, threadPools, binaryStore, data,
processId, decoder, encoder, stringFactory, binaryFactory, booleanFactory, dateFactory,
decimalFactory, doubleFactory, longFactory, nameFactory, pathFactory, referenceFactory,
weakReferenceFactory, simpleReferenceFactory, uriFactory, objectFactory);
}
/**
* Create a new execution context that mirrors this context but that contains the supplied data. Note that the supplied map is
* always copied to ensure that it is immutable.
*
* @param data the data that is to be affiliated with the resulting context or null if the resulting context should have no
* data
* @return the execution context that is identical with this execution context, but which uses the supplied data; never null
* @since 2.0
*/
public ExecutionContext with( Map<String, String> data ) {
Map<String, String> newData = data;
if (newData == null) {
if (this.data.isEmpty()) return this;
} else {
// Copy the data in the map ...
newData = Collections.unmodifiableMap(new HashMap<String, String>(data));
}
return new ExecutionContext(securityContext, namespaceRegistry, propertyFactory, threadPools, binaryStore, newData,
processId, decoder, encoder, stringFactory, binaryFactory, booleanFactory, dateFactory,
decimalFactory, doubleFactory, longFactory, nameFactory, pathFactory, referenceFactory,
weakReferenceFactory, simpleReferenceFactory, uriFactory, objectFactory);
}
protected ExecutionContext with( ReferenceFactory referenceFactory ) {
ReferenceFactory strongFactory = this.referenceFactory;
ReferenceFactory weakFactory = this.weakReferenceFactory;
ReferenceFactory simpleReferenceFactory = this.simpleReferenceFactory;
if (referenceFactory.getPropertyType() == PropertyType.REFERENCE) {
strongFactory = referenceFactory;
} else if (referenceFactory.getPropertyType() == PropertyType.SIMPLEREFERENCE) {
simpleReferenceFactory = referenceFactory;
} else {
weakFactory = referenceFactory;
}
return new ExecutionContext(securityContext, namespaceRegistry, propertyFactory, threadPools, binaryStore, data,
processId, decoder, encoder, stringFactory, binaryFactory, booleanFactory, dateFactory,
decimalFactory, doubleFactory, longFactory, nameFactory, pathFactory, strongFactory,
weakFactory, simpleReferenceFactory, uriFactory, objectFactory);
}
/**
* Create a new execution context that mirrors this context but that contains the supplied key-value pair in the new context's
* data.
*
* @param key the key for the new data that is to be affiliated with the resulting context
* @param value the data value to be affiliated with the supplied key in the resulting context, or null if an existing data
* affiliated with the key should be removed in the resulting context
* @return the execution context that is identical with this execution context, but which uses the supplied data; never null
* @since 2.0
*/
public ExecutionContext with( String key,
String value ) {
Map<String, String> newData = data;
if (value == null) {
// Remove the value with the key ...
if (this.data.isEmpty() || !this.data.containsKey(key)) {
// nothing to remove
return this;
}
newData = new HashMap<String, String>(data);
newData.remove(key);
newData = Collections.unmodifiableMap(newData);
} else {
// We are to add the value ...
newData = new HashMap<String, String>(data);
newData.put(key, value);
newData = Collections.unmodifiableMap(newData);
}
return new ExecutionContext(securityContext, namespaceRegistry, propertyFactory, threadPools, binaryStore, newData,
processId, decoder, encoder, stringFactory, binaryFactory, booleanFactory, dateFactory,
decimalFactory, doubleFactory, longFactory, nameFactory, pathFactory, referenceFactory,
weakReferenceFactory, simpleReferenceFactory, uriFactory, objectFactory);
}
/**
* Create a new execution context that mirrors this context but that contains the supplied process identifier.
*
* @param processId the identifier of the process
* @return the execution context that is identical with this execution context, but which uses the supplied process
* identifier; never null
* @since 2.1
*/
public ExecutionContext with( String processId ) {
return new ExecutionContext(securityContext, namespaceRegistry, propertyFactory, threadPools, binaryStore, data,
processId, decoder, encoder, stringFactory, binaryFactory, booleanFactory, dateFactory,
decimalFactory, doubleFactory, longFactory, nameFactory, pathFactory, referenceFactory,
weakReferenceFactory, simpleReferenceFactory, uriFactory, objectFactory);
}
@Override
public ExecutionContext clone() {
return new ExecutionContext(this);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("Execution context for ");
if (getSecurityContext() == null) sb.append("null");
else sb.append(getSecurityContext().getUserName());
sb.append(" (").append(id).append(')');
return sb.toString();
}
/**
* Method that initializes the default namespaces for namespace registries.
*
* @param namespaceRegistry the namespace registry
*/
protected void initializeDefaultNamespaces( NamespaceRegistry namespaceRegistry ) {
if (namespaceRegistry == null) return;
namespaceRegistry.register(JcrLexicon.Namespace.PREFIX, JcrLexicon.Namespace.URI);
namespaceRegistry.register(JcrMixLexicon.Namespace.PREFIX, JcrMixLexicon.Namespace.URI);
namespaceRegistry.register(JcrNtLexicon.Namespace.PREFIX, JcrNtLexicon.Namespace.URI);
namespaceRegistry.register(ModeShapeLexicon.Namespace.PREFIX, ModeShapeLexicon.Namespace.URI);
}
/**
* Default security context that confers no roles.
*/
private static class NullSecurityContext implements SecurityContext {
@Override
public boolean isAnonymous() {
return true;
}
@Override
public String getUserName() {
return null;
}
@Override
public boolean hasRole( String roleName ) {
return false;
}
@Override
public void logout() {
}
}
@SuppressWarnings( "synthetic-access" )
protected final class ContextFactories implements ValueFactories {
@Override
public TypeSystem getTypeSystem() {
return typeSystem;
}
/**
* @return namespaceRegistry
*/
public NamespaceRegistry getNamespaceRegistry() {
return namespaceRegistry;
}
@Override
public BinaryFactory getBinaryFactory() {
return binaryFactory;
}
@Override
public ValueFactory<Boolean> getBooleanFactory() {
return booleanFactory;
}
@Override
public DateTimeFactory getDateFactory() {
return dateFactory;
}
@Override
public ValueFactory<BigDecimal> getDecimalFactory() {
return decimalFactory;
}
@Override
public ValueFactory<Double> getDoubleFactory() {
return doubleFactory;
}
@Override
public ValueFactory<Long> getLongFactory() {
return longFactory;
}
@Override
public NameFactory getNameFactory() {
return nameFactory;
}
@Override
public PathFactory getPathFactory() {
return pathFactory;
}
@Override
public ReferenceFactory getReferenceFactory() {
return referenceFactory;
}
@Override
public ReferenceFactory getWeakReferenceFactory() {
return weakReferenceFactory;
}
@Override
public ReferenceFactory getSimpleReferenceFactory() {
return simpleReferenceFactory;
}
@Override
public StringFactory getStringFactory() {
return stringFactory;
}
@Override
public UriFactory getUriFactory() {
return uriFactory;
}
@Override
public ValueFactory<Object> getObjectFactory() {
return objectFactory;
}
/**
* <p>
* {@inheritDoc}
* </p>
* <p>
* This implementation always iterates over the instances return by the <code>get*Factory()</code> methods.
* </p>
*/
@Override
public Iterator<ValueFactory<?>> iterator() {
return new ValueFactoryIterator();
}
@Override
public ValueFactory<?> getValueFactory( PropertyType type ) {
CheckArg.isNotNull(type, "type");
switch (type) {
case BINARY:
return getBinaryFactory();
case BOOLEAN:
return getBooleanFactory();
case DATE:
return getDateFactory();
case DECIMAL:
return getDecimalFactory();
case DOUBLE:
return getDoubleFactory();
case LONG:
return getLongFactory();
case NAME:
return getNameFactory();
case PATH:
return getPathFactory();
case REFERENCE:
return getReferenceFactory();
case WEAKREFERENCE:
return getWeakReferenceFactory();
case SIMPLEREFERENCE:
return getSimpleReferenceFactory();
case STRING:
return getStringFactory();
case URI:
return getUriFactory();
case OBJECT:
return getObjectFactory();
}
return getObjectFactory();
}
@Override
public ValueFactory<?> getValueFactory( Object prototype ) {
CheckArg.isNotNull(prototype, "prototype");
PropertyType inferredType = PropertyType.discoverType(prototype);
assert inferredType != null;
return getValueFactory(inferredType);
}
protected class ValueFactoryIterator implements Iterator<ValueFactory<?>> {
private final Iterator<PropertyType> propertyTypeIter = PropertyType.iterator();
protected ValueFactoryIterator() {
}
@Override
public boolean hasNext() {
return propertyTypeIter.hasNext();
}
@Override
public ValueFactory<?> next() {
PropertyType nextType = propertyTypeIter.next();
return getValueFactory(nextType);
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
}
}