| /* |
| * 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.directory.shared.ldap.codec.standalone; |
| |
| |
| import java.io.File; |
| import java.nio.ByteBuffer; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.apache.directory.shared.asn1.DecoderException; |
| import org.apache.directory.shared.asn1.EncoderException; |
| import org.apache.directory.shared.asn1.ber.Asn1Container; |
| import org.apache.directory.shared.ldap.codec.BasicControlDecorator; |
| import org.apache.directory.shared.ldap.codec.LdapMessageContainer; |
| import org.apache.directory.shared.ldap.codec.api.CodecControl; |
| import org.apache.directory.shared.ldap.codec.api.ControlFactory; |
| import org.apache.directory.shared.ldap.codec.api.ExtendedRequestFactory; |
| import org.apache.directory.shared.ldap.codec.api.LdapCodecService; |
| import org.apache.directory.shared.ldap.codec.api.UnsolicitedResponseFactory; |
| import org.apache.directory.shared.ldap.codec.controls.cascade.CascadeFactory; |
| import org.apache.directory.shared.ldap.codec.controls.manageDsaIT.ManageDsaITFactory; |
| import org.apache.directory.shared.ldap.codec.controls.search.entryChange.EntryChangeFactory; |
| import org.apache.directory.shared.ldap.codec.controls.search.pagedSearch.PagedResultsFactory; |
| import org.apache.directory.shared.ldap.codec.controls.search.persistentSearch.PersistentSearchFactory; |
| import org.apache.directory.shared.ldap.codec.controls.search.subentries.SubentriesFactory; |
| import org.apache.directory.shared.ldap.codec.decorators.MessageDecorator; |
| import org.apache.directory.shared.ldap.codec.protocol.mina.LdapProtocolCodecFactory; |
| import org.apache.directory.shared.ldap.model.message.Control; |
| import org.apache.directory.shared.ldap.model.message.ExtendedResponse; |
| import org.apache.directory.shared.ldap.model.message.ExtendedResponseImpl; |
| import org.apache.directory.shared.ldap.model.message.Message; |
| import org.apache.directory.shared.ldap.model.message.controls.OpaqueControl; |
| import org.apache.directory.shared.util.exception.NotImplementedException; |
| import org.apache.felix.framework.Felix; |
| import org.apache.felix.framework.util.FelixConstants; |
| import org.apache.mina.filter.codec.ProtocolCodecFactory; |
| import org.osgi.framework.BundleActivator; |
| import org.osgi.framework.BundleException; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| |
| /** |
| * The default {@link org.apache.directory.shared.ldap.codec.api.LdapCodecService} implementation. |
| * |
| * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> |
| * @version $Rev$, $Date$ |
| */ |
| public class StandaloneLdapCodecService implements LdapCodecService |
| { |
| /** Missing felix constants for cache directory locking */ |
| public static final String FELIX_CACHE_LOCKING = "felix.cache.locking"; |
| |
| /** Missing felix constants for cache root directory path */ |
| public static final String FELIX_CACHE_ROOTDIR = "felix.cache.rootdir"; |
| |
| /** A logger */ |
| private static final Logger LOG = LoggerFactory.getLogger( StandaloneLdapCodecService.class ); |
| |
| /** |
| * This should be constructed at class initialization time by reading the |
| * Export-Package attribute of the this jar's manifest file. |
| */ |
| private static final String[] SYSTEM_PACKAGES = |
| { |
| "org.slf4j; version=1.6.0", |
| "org.apache.directory.shared.i18n; version=1.0.0", |
| "org.apache.directory.shared.util; version=1.0.0", |
| "org.apache.directory.shared.util.exception; version=1.0.0", |
| "org.apache.directory.shared.asn1; version=1.0.0", |
| "org.apache.directory.shared.asn1.util; version=1.0.0", |
| "org.apache.directory.shared.asn1.ber; version=1.0.0", |
| "org.apache.directory.shared.asn1.ber.tlv; version=1.0.0", |
| "org.apache.directory.shared.asn1.ber.grammar; version=1.0.0", |
| "org.apache.directory.shared.asn1.actions; version=1.0.0", |
| "org.apache.directory.shared.ldap.asn1.ber; version=1.0.0", |
| "org.apache.directory.shared.ldap.model; version=1.0.0", |
| "org.apache.directory.shared.ldap.model.exception; version=1.0.0", |
| "org.apache.directory.shared.ldap.model.filter; version=1.0.0", |
| "org.apache.directory.shared.ldap.model.name; version=1.0.0", |
| "org.apache.directory.shared.ldap.model.entry; version=1.0.0", |
| "org.apache.directory.shared.ldap.model.schema; version=1.0.0", |
| "org.apache.directory.shared.ldap.model.message; version=1.0.0", |
| "org.apache.directory.shared.ldap.model.message.controls; version=1.0.0", |
| "org.apache.directory.shared.ldap.codec.controls; version=1.0.0", |
| "org.apache.directory.shared.ldap.codec.api; version=1.0.0" |
| }; |
| |
| /** System property checked if the pluginProperty is null */ |
| public static final String PLUGIN_DIRECTORY_PROPERTY = "codec.plugin.directory"; |
| |
| /** The map of registered {@link org.apache.directory.shared.ldap.codec.api.ControlFactory}'s */ |
| private Map<String,ControlFactory<?,?>> controlFactories = new HashMap<String, ControlFactory<?,?>>(); |
| |
| /** The map of registered {@link org.apache.directory.shared.ldap.codec.api.ExtendedRequestFactory}'s by request OID */ |
| private Map<String,ExtendedRequestFactory<?,?>> extReqFactories = new HashMap<String, ExtendedRequestFactory<?,?>>(); |
| |
| /** The map of registered {@link UnsolicitedResponseFactory}'s by request OID */ |
| private Map<String,UnsolicitedResponseFactory<?>> unsolicitedFactories = new HashMap<String, UnsolicitedResponseFactory<?>>(); |
| |
| /** The codec's {@link BundleActivator} */ |
| private CodecHostActivator activator; |
| |
| /** The embedded {@link Felix} instance */ |
| private Felix felix; |
| |
| /** Felix's bundle cache directory */ |
| private final File cacheDirectory; |
| |
| /** The plugin (bundle) containing directory to load codec extensions from */ |
| private final File pluginDirectory; |
| |
| |
| /** |
| * Creates a new instance of StandaloneLdapCodecService. Optionally checks for |
| * system property {@link #PLUGIN_DIRECTORY_PROPERTY}. Intended for use by |
| * unit test running tools like Maven's surefire: |
| * <pre> |
| * <properties> |
| * <codec.plugin.directory>${project.build.directory}/pluginDirectory</codec.plugin.directory> |
| * </properties> |
| * |
| * <build> |
| * <plugins> |
| * <plugin> |
| * <artifactId>maven-surefire-plugin</artifactId> |
| * <groupId>org.apache.maven.plugins</groupId> |
| * <configuration> |
| * <systemPropertyVariables> |
| * <workingDirectory>${basedir}/target</workingDirectory> |
| * <felix.cache.rootdir> |
| * ${project.build.directory} |
| * </felix.cache.rootdir> |
| * <felix.cache.locking> |
| * true |
| * </felix.cache.locking> |
| * <org.osgi.framework.storage.clean> |
| * onFirstInit |
| * </org.osgi.framework.storage.clean> |
| * <org.osgi.framework.storage> |
| * osgi-cache |
| * </org.osgi.framework.storage> |
| * <codec.plugin.directory> |
| * ${codec.plugin.directory} |
| * </codec.plugin.directory> |
| * </systemPropertyVariables> |
| * </configuration> |
| * </plugin> |
| * |
| * <plugin> |
| * <groupId>org.apache.maven.plugins</groupId> |
| * <artifactId>maven-dependency-plugin</artifactId> |
| * <executions> |
| * <execution> |
| * <id>copy</id> |
| * <phase>compile</phase> |
| * <goals> |
| * <goal>copy</goal> |
| * </goals> |
| * <configuration> |
| * <artifactItems> |
| * <artifactItem> |
| * <groupId>${project.groupId}</groupId> |
| * <artifactId>shared-ldap-extras-codec</artifactId> |
| * <version>${project.version}</version> |
| * <outputDirectory>${codec.plugin.directory}</outputDirectory> |
| * </artifactItem> |
| * </artifactItems> |
| * </configuration> |
| * </execution> |
| * </executions> |
| * </plugin> |
| * </plugins> |
| * </build> |
| * </pre> |
| */ |
| public StandaloneLdapCodecService() |
| { |
| this( null, null ); |
| } |
| |
| |
| /** |
| * Uses system properties and default considerations to create a cache |
| * directory that can be used when one is not provided. |
| * |
| * @see FelixConstants#FRAMEWORK_STORAGE |
| * @return The cache directory default. |
| */ |
| private File getCacheDirectoryDefault() |
| { |
| String frameworkStorage = System.getProperties().getProperty( FelixConstants.FRAMEWORK_STORAGE ); |
| LOG.info( "{}: {}", FelixConstants.FRAMEWORK_STORAGE, frameworkStorage ); |
| |
| String felixCacheRootdir = System.getProperties().getProperty( FELIX_CACHE_ROOTDIR ); |
| LOG.info( "{}: {}", FELIX_CACHE_ROOTDIR, felixCacheRootdir ); |
| |
| try |
| { |
| if ( frameworkStorage == null && felixCacheRootdir == null ) |
| { |
| return new File( File.createTempFile( "dummy", null ).getParentFile(), |
| "osgi-cache-" + Integer.toString( this.hashCode() ) ); |
| } |
| else if ( frameworkStorage == null && felixCacheRootdir != null ) |
| { |
| return new File( new File ( felixCacheRootdir ), |
| "osgi-cache-" + Integer.toString( this.hashCode() ) ); |
| } |
| else if ( frameworkStorage != null && felixCacheRootdir == null ) |
| { |
| return new File( frameworkStorage + "-" + Integer.toString( this.hashCode() ) ); |
| } |
| |
| // else if both are not null now |
| return new File( new File ( felixCacheRootdir ), |
| frameworkStorage + "-" + Integer.toString( this.hashCode() ) ); |
| } |
| catch ( Exception e ) |
| { |
| String message = "Failure to create temporary cache directory: " + e.getMessage(); |
| LOG.warn( message, e ); |
| return null; |
| } |
| } |
| |
| |
| /** |
| * Gets the optional system property value for the pluginDirectory if one |
| * is provided. |
| * |
| * @return The path for the pluginDirectory or null if not provided. |
| */ |
| private File getPluginDirectoryDefault() |
| { |
| String value = System.getProperty( StandaloneLdapCodecService.PLUGIN_DIRECTORY_PROPERTY ); |
| LOG.info( "{}: {}", PLUGIN_DIRECTORY_PROPERTY, value ); |
| |
| if ( value == null ) |
| { |
| return null; |
| } |
| |
| return new File( value ); |
| } |
| |
| |
| /** |
| * Creates a new instance of StandaloneLdapCodecService. |
| */ |
| public StandaloneLdapCodecService( File pluginDirectory, File cacheDirectory ) |
| { |
| |
| // ------------------------------------------------------------------- |
| // Handle plugin directory |
| // ------------------------------------------------------------------- |
| |
| if ( pluginDirectory == null ) |
| { |
| this.pluginDirectory = getPluginDirectoryDefault(); |
| LOG.info( "Null plugin directory provided, using default instead: {}", this.pluginDirectory ); |
| } |
| else |
| { |
| this.pluginDirectory = pluginDirectory; |
| LOG.info( "Valid plugin directory provided: {}", this.pluginDirectory ); |
| } |
| |
| if ( this.pluginDirectory == null ) |
| { |
| // do nothing |
| } |
| else if ( ! this.pluginDirectory.exists() ) |
| { |
| this.pluginDirectory.mkdirs(); |
| } |
| |
| if ( this.pluginDirectory == null ) |
| { |
| // do nothing |
| } |
| else if ( ! this.pluginDirectory.isDirectory() ) |
| { |
| String msg = "The provided plugin directory is not a directory:" + this.pluginDirectory.getAbsolutePath(); |
| LOG.error( msg ); |
| throw new IllegalArgumentException( msg ); |
| } |
| else if ( ! this.pluginDirectory.canRead() ) |
| { |
| String msg = "The provided plugin directory is not readable:" + this.pluginDirectory.getAbsolutePath(); |
| LOG.error( msg ); |
| throw new IllegalArgumentException( msg ); |
| } |
| |
| |
| // ------------------------------------------------------------------- |
| // Handle cache directory |
| // ------------------------------------------------------------------- |
| |
| if ( cacheDirectory == null ) |
| { |
| this.cacheDirectory = getCacheDirectoryDefault(); |
| LOG.info( "Null cache directory provided, using default instead: {}", this.cacheDirectory ); |
| } |
| else |
| { |
| this.cacheDirectory = cacheDirectory; |
| LOG.info( "Valid cache directory provided: {}", this.cacheDirectory ); |
| } |
| |
| if ( this.cacheDirectory == null ) |
| { |
| // do nothing |
| } |
| else if ( ! this.cacheDirectory.exists() ) |
| { |
| this.cacheDirectory.mkdirs(); |
| } |
| |
| if ( this.cacheDirectory == null ) |
| { |
| // do nothing |
| } |
| else if ( ! this.cacheDirectory.isDirectory() ) |
| { |
| String msg = "The provided cache directory is not a directory:" + this.cacheDirectory.getAbsolutePath(); |
| LOG.error( msg ); |
| throw new IllegalArgumentException( msg ); |
| } |
| else if ( ! this.cacheDirectory.canRead() ) |
| { |
| String msg = "The provided cache directory is not readable:" + this.cacheDirectory.getAbsolutePath(); |
| LOG.error( msg ); |
| throw new IllegalArgumentException( msg ); |
| } |
| |
| loadStockControls(); |
| setupFelix(); |
| } |
| |
| |
| /** |
| * Assembles the <code>org.osgi.framework.system.packages.extra</code> list |
| * of system packages exported by the embedding host to interact with bundles |
| * running inside {@link Felix}. |
| * |
| * @return A comma delimited list of exported host packages. |
| */ |
| private String getSystemPackages() |
| { |
| StringBuilder sb = new StringBuilder(); |
| int ii = 0; |
| |
| do |
| { |
| // add comma if we're not at start and have more left |
| if ( ii > 0 && ii < SYSTEM_PACKAGES.length ) |
| { |
| sb.append( ',' ); |
| } |
| |
| sb.append( SYSTEM_PACKAGES[ii] ); |
| ii++; |
| } |
| while( ii < SYSTEM_PACKAGES.length ); |
| |
| LOG.info( "System packages shared by host: " + SYSTEM_PACKAGES ); |
| |
| return sb.toString(); |
| } |
| |
| |
| /** |
| * Sets up a {@link Felix} instance. |
| */ |
| private void setupFelix() |
| { |
| // initialize activator and setup system bundle activators |
| activator = new CodecHostActivator( this ); |
| List<BundleActivator> activators = new ArrayList<BundleActivator>(); |
| activators.add( activator ); |
| |
| // setup configuration for felix |
| Map<String, Object> config = new HashMap<String, Object>(); |
| config.put( FelixConstants.SYSTEMBUNDLE_ACTIVATORS_PROP, activators ); |
| config.put( FelixConstants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, getSystemPackages() ); |
| config.put( FELIX_CACHE_ROOTDIR, this.cacheDirectory.getParent() ); |
| config.put( FelixConstants.FRAMEWORK_STORAGE, this.cacheDirectory.getName() ); |
| |
| if ( System.getProperties().getProperty( FelixConstants.FRAMEWORK_STORAGE_CLEAN ) != null ) |
| { |
| String cleanMode = System.getProperties().getProperty( FelixConstants.FRAMEWORK_STORAGE_CLEAN ); |
| config.put( FelixConstants.FRAMEWORK_STORAGE_CLEAN, cleanMode ); |
| LOG.info( "Using framework storage clean value from sytem properties: {}", cleanMode ); |
| } |
| else |
| { |
| config.put( FelixConstants.FRAMEWORK_STORAGE_CLEAN, "none" ); |
| LOG.info( "Using framework storage clean defaults: none" ); |
| } |
| |
| if ( System.getProperties().getProperty( FELIX_CACHE_LOCKING ) != null ) |
| { |
| String lockCache = System.getProperties().getProperty( FELIX_CACHE_LOCKING ); |
| config.put( FELIX_CACHE_LOCKING, lockCache ); |
| LOG.info( "Using framework cache locking setting from sytem properties: {}", lockCache ); |
| } |
| else |
| { |
| config.put( FELIX_CACHE_LOCKING, "true" ); |
| LOG.info( "Using default for cache locking: enabled" ); |
| } |
| |
| // instantiate and start up felix |
| felix = new Felix( config ); |
| try |
| { |
| felix.start(); |
| } |
| catch ( BundleException e ) |
| { |
| String message = "Failed to start embedded felix instance: " + e.getMessage(); |
| LOG.error( message, e ); |
| throw new RuntimeException( message, e ); |
| } |
| } |
| |
| |
| /** |
| * Shuts down the codec and its embedded {@link Felix} instance. |
| */ |
| public void shutdown() |
| { |
| LOG.info( "Attempt to shutdown the codec service" ); |
| |
| try |
| { |
| felix.stop(); |
| felix.waitForStop( 0 ); |
| } |
| catch ( Exception e ) |
| { |
| String message = "Failed to stop embedded felix instance: " + e.getMessage(); |
| LOG.error( message, e ); |
| throw new RuntimeException( message, e ); |
| } |
| } |
| |
| |
| /** |
| * Loads the Controls implement out of the box in the codec. |
| */ |
| private void loadStockControls() |
| { |
| ControlFactory<?, ?> factory = new CascadeFactory( this ); |
| controlFactories.put( factory.getOid(), factory ); |
| LOG.info( "Registered pre-bundled control factory: {}", factory.getOid() ); |
| |
| factory = new EntryChangeFactory( this ); |
| controlFactories.put( factory.getOid(), factory ); |
| LOG.info( "Registered pre-bundled control factory: {}", factory.getOid() ); |
| |
| factory = new ManageDsaITFactory( this ); |
| controlFactories.put( factory.getOid(), factory ); |
| LOG.info( "Registered pre-bundled control factory: {}", factory.getOid() ); |
| |
| factory = new PagedResultsFactory( this ); |
| controlFactories.put( factory.getOid(), factory ); |
| LOG.info( "Registered pre-bundled control factory: {}", factory.getOid() ); |
| |
| factory = new PersistentSearchFactory( this ); |
| controlFactories.put( factory.getOid(), factory ); |
| LOG.info( "Registered pre-bundled control factory: {}", factory.getOid() ); |
| |
| factory = new SubentriesFactory( this ); |
| controlFactories.put( factory.getOid(), factory ); |
| LOG.info( "Registered pre-bundled control factory: {}", factory.getOid() ); |
| } |
| |
| |
| //------------------------------------------------------------------------- |
| // LdapCodecService implementation methods |
| //------------------------------------------------------------------------- |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public ControlFactory<?,?> registerControl( ControlFactory<?,?> factory ) |
| { |
| return controlFactories.put( factory.getOid(), factory ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public ControlFactory<?,?> unregisterControl( String oid ) |
| { |
| return controlFactories.remove( oid ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public Iterator<String> registeredControls() |
| { |
| return Collections.unmodifiableSet( controlFactories.keySet() ).iterator(); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public boolean isControlRegistered( String oid ) |
| { |
| return controlFactories.containsKey( oid ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public Iterator<String> registeredExtendedRequests() |
| { |
| return Collections.unmodifiableSet( extReqFactories.keySet() ).iterator(); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public ExtendedRequestFactory<?, ?> registerExtendedRequest( ExtendedRequestFactory<?,?> factory ) |
| { |
| return extReqFactories.put( factory.getOid(), factory ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| * |
| * @TODO - finish this up and add factory registration capabilities, |
| * of course there is one default mechanism for now. |
| */ |
| public ProtocolCodecFactory newProtocolCodecFactory( boolean client ) |
| { |
| if ( client ) |
| { |
| return new LdapProtocolCodecFactory( this ); |
| } |
| else |
| { |
| throw new NotImplementedException( |
| "Filters may be different here, and we're probably going to " + |
| "want to have a protocol codec factory registration mechanism" + |
| "since this way we can swap in and out MINA/Grizzly" ); |
| } |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public CodecControl<? extends Control> newControl( String oid ) |
| { |
| ControlFactory<?,?> factory = controlFactories.get( oid ); |
| |
| if ( factory == null ) |
| { |
| return new BasicControlDecorator<Control>( this, new OpaqueControl( oid ) ); |
| } |
| |
| return factory.newCodecControl(); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @SuppressWarnings("unchecked") |
| public CodecControl<? extends Control> newControl( Control control ) |
| { |
| if ( control == null ) |
| { |
| throw new NullPointerException( "Control argument was null." ); |
| } |
| |
| // protect agains being multiply decorated |
| if ( control instanceof CodecControl ) |
| { |
| return (org.apache.directory.shared.ldap.codec.api.CodecControl<?> )control; |
| } |
| |
| @SuppressWarnings("rawtypes") |
| ControlFactory factory = controlFactories.get( control.getOid() ); |
| |
| if ( factory == null ) |
| { |
| return new BasicControlDecorator<Control>( this, control ); |
| } |
| |
| return factory.newCodecControl( control ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public javax.naming.ldap.Control toJndiControl( Control control ) throws EncoderException |
| { |
| CodecControl<? extends Control> decorator = newControl( control ); |
| ByteBuffer bb = ByteBuffer.allocate( decorator.computeLength() ); |
| decorator.encode( bb ); |
| bb.flip(); |
| javax.naming.ldap.BasicControl jndiControl = |
| new javax.naming.ldap.BasicControl( control.getOid(), control.isCritical(), bb.array() ); |
| return jndiControl; |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public Control fromJndiControl( javax.naming.ldap.Control control ) throws DecoderException |
| { |
| @SuppressWarnings("rawtypes") |
| ControlFactory factory = controlFactories.get( control.getID() ); |
| |
| if ( factory == null ) |
| { |
| OpaqueControl ourControl = new OpaqueControl( control.getID() ); |
| ourControl.setCritical( control.isCritical() ); |
| BasicControlDecorator<Control> decorator = |
| new BasicControlDecorator<Control>( this, ourControl ); |
| decorator.setValue( control.getEncodedValue() ); |
| return decorator; |
| } |
| |
| @SuppressWarnings("unchecked") |
| CodecControl<? extends Control> ourControl = factory.newCodecControl(); |
| ourControl.setCritical( control.isCritical() ); |
| ourControl.setValue( control.getEncodedValue() ); |
| ourControl.decode( control.getEncodedValue() ); |
| return ourControl; |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public Asn1Container newMessageContainer() |
| { |
| return new LdapMessageContainer<MessageDecorator<? extends Message>>( this ); |
| } |
| |
| |
| /** |
| * Gets the plugin directory containing codec extension bundles to load. |
| * If null, the service checks to see if system properties were used to |
| * specify the plugin directory. |
| * |
| * @see {@link #PLUGIN_DIRECTORY_PROPERTY} |
| * @return The directory containing plugins. |
| */ |
| public File getPluginDirectory() |
| { |
| return pluginDirectory; |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public Iterator<String> registeredUnsolicitedResponses() |
| { |
| return Collections.unmodifiableSet( unsolicitedFactories.keySet() ).iterator(); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public UnsolicitedResponseFactory<?> registerUnsolicitedResponse( UnsolicitedResponseFactory<?> factory ) |
| { |
| return unsolicitedFactories.put( factory.getOid(), factory ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public javax.naming.ldap.ExtendedResponse toJndi( final ExtendedResponse modelResponse ) throws EncoderException |
| { |
| final byte[] encodedValue = new byte[ modelResponse.getEncodedValue().length ]; |
| System.arraycopy( modelResponse.getEncodedValue(), 0, encodedValue, 0, modelResponse.getEncodedValue().length ); |
| |
| return new javax.naming.ldap.ExtendedResponse() |
| { |
| private static final long serialVersionUID = 2955142105375495493L; |
| |
| public String getID() |
| { |
| return modelResponse.getID(); |
| } |
| |
| public byte[] getEncodedValue() |
| { |
| return encodedValue; |
| } |
| }; |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public ExtendedResponse fromJndi( javax.naming.ldap.ExtendedResponse jndiResponse ) throws DecoderException |
| { |
| ExtendedResponse modelResponse; |
| ExtendedRequestFactory<?,?> extendedRequestFactory = extReqFactories.get( jndiResponse.getID() ); |
| UnsolicitedResponseFactory<?> unsolicitedResponseFactory = unsolicitedFactories.get( jndiResponse.getID() ); |
| |
| if ( unsolicitedResponseFactory != null ) |
| { |
| modelResponse = unsolicitedResponseFactory.newResponse( jndiResponse.getEncodedValue() ); |
| } |
| else if ( extendedRequestFactory != null ) |
| { |
| modelResponse = extendedRequestFactory.newResponse( jndiResponse.getEncodedValue() ); |
| } |
| else |
| { |
| modelResponse = new ExtendedResponseImpl( jndiResponse.getID() ); |
| modelResponse.setResponseValue( jndiResponse.getEncodedValue() ); |
| } |
| |
| return modelResponse; |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public ExtendedRequestFactory<?, ?> unregisterExtendedRequest( String oid ) |
| { |
| return extReqFactories.remove( oid ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public UnsolicitedResponseFactory<?> unregisterUnsolicitedResponse( String oid ) |
| { |
| return unsolicitedFactories.remove( oid ); |
| } |
| } |