/* * 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.Locale; 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.LongValueFactory; import org.modeshape.jcr.value.basic.ModeShapeDateTimeValueFactory; 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; private final Locale locale; /** * 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, 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, context.locale); } /** * 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 * @param locale an optional Locale than can be used; if null it will be ignored */ 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, Locale locale ) { 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 ModeShapeDateTimeValueFactory(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; this.locale = locale; // Assign the things that depend on a ValueFactories implementation ... this.typeSystem = new ValueTypeSystem(valueFactories, locale); 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, int maxPoolSize ) { return this.threadPools.getCachedTreadPool(name, maxPoolSize); } @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, locale); } /** * 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, locale); } /** * 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, locale); } /** * 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, locale); } /** * 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, locale); } /** * 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, locale); } 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, locale); } /** * 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, locale); } /** * 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, locale); } /** * Create a new execution context that mirrors this context but that contains the supplied locale. * * @param locale a {@code Locale} instance * @return the execution context that is identical with this execution context, but which uses the supplied locale; never null * @since 4.5 */ public ExecutionContext with(Locale locale) { 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, locale); } @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(); } } } }