Return-Path: Delivered-To: apmail-directory-commits-archive@www.apache.org Received: (qmail 31316 invoked from network); 10 Feb 2011 03:36:52 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 10 Feb 2011 03:36:52 -0000 Received: (qmail 59811 invoked by uid 500); 10 Feb 2011 03:36:52 -0000 Delivered-To: apmail-directory-commits-archive@directory.apache.org Received: (qmail 59789 invoked by uid 500); 10 Feb 2011 03:36:51 -0000 Mailing-List: contact commits-help@directory.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@directory.apache.org Delivered-To: mailing list commits@directory.apache.org Received: (qmail 59782 invoked by uid 99); 10 Feb 2011 03:36:50 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 10 Feb 2011 03:36:50 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 10 Feb 2011 03:36:48 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 0F9F42388A41; Thu, 10 Feb 2011 03:36:28 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1069216 - in /directory/shared/branches/m1/ldap-codec/src/main/java/org/apache/directory/shared/ldap/codec/standalone: ./ CodecHostActivator.java StandaloneLdapCodecService.java Date: Thu, 10 Feb 2011 03:36:28 -0000 To: commits@directory.apache.org From: akarasulu@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20110210033628.0F9F42388A41@eris.apache.org> Author: akarasulu Date: Thu Feb 10 03:36:27 2011 New Revision: 1069216 URL: http://svn.apache.org/viewvc?rev=1069216&view=rev Log: DIRSHARED-91: forgot to svn add the new standalone package Added: directory/shared/branches/m1/ldap-codec/src/main/java/org/apache/directory/shared/ldap/codec/standalone/ directory/shared/branches/m1/ldap-codec/src/main/java/org/apache/directory/shared/ldap/codec/standalone/CodecHostActivator.java directory/shared/branches/m1/ldap-codec/src/main/java/org/apache/directory/shared/ldap/codec/standalone/StandaloneLdapCodecService.java Added: directory/shared/branches/m1/ldap-codec/src/main/java/org/apache/directory/shared/ldap/codec/standalone/CodecHostActivator.java URL: http://svn.apache.org/viewvc/directory/shared/branches/m1/ldap-codec/src/main/java/org/apache/directory/shared/ldap/codec/standalone/CodecHostActivator.java?rev=1069216&view=auto ============================================================================== --- directory/shared/branches/m1/ldap-codec/src/main/java/org/apache/directory/shared/ldap/codec/standalone/CodecHostActivator.java (added) +++ directory/shared/branches/m1/ldap-codec/src/main/java/org/apache/directory/shared/ldap/codec/standalone/CodecHostActivator.java Thu Feb 10 03:36:27 2011 @@ -0,0 +1,109 @@ +/* + * 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.io.FileFilter; + +import org.apache.directory.shared.ldap.codec.api.LdapCodecService; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; + + +/** + * The {@link BundleActivator} for the codec. This implementation class is + * + * @author Apache Directory Project + */ +public class CodecHostActivator implements BundleActivator +{ + private StandaloneLdapCodecService codec; + private ServiceRegistration registration; + private BundleContext bundleContext; + + + public CodecHostActivator( StandaloneLdapCodecService codec ) + { + this.codec = codec; + } + + + /** + * {@inheritDoc} + */ + public void start( BundleContext bundleContext ) throws Exception + { + this.bundleContext = bundleContext; + + registration = bundleContext.registerService( LdapCodecService.class.getName(), codec, null ); + + if ( codec.getPluginDirectory() != null ) + { + File[] files = codec.getPluginDirectory().listFiles( new FileFilter() + { + public boolean accept( File pathname ) + { + return + pathname.canRead() + && + pathname.isFile() + && + pathname.getAbsolutePath().endsWith( ".jar" ); + } + }); + + for ( File file : files ) + { + Bundle bundle = bundleContext.installBundle( file.toURI().toURL().toExternalForm() ); + bundle.start(); + } + } + } + + + /** + * {@inheritDoc} + */ + public void stop( BundleContext bundleContext ) throws Exception + { + registration.unregister(); + + this.bundleContext = null; + } + + + /** + * Gets the Bundles installed. + * + * @return The Bundles installed. + */ + public Bundle[] getBundles() + { + if ( bundleContext != null ) + { + return bundleContext.getBundles(); + } + + return null; + } +} Added: directory/shared/branches/m1/ldap-codec/src/main/java/org/apache/directory/shared/ldap/codec/standalone/StandaloneLdapCodecService.java URL: http://svn.apache.org/viewvc/directory/shared/branches/m1/ldap-codec/src/main/java/org/apache/directory/shared/ldap/codec/standalone/StandaloneLdapCodecService.java?rev=1069216&view=auto ============================================================================== --- directory/shared/branches/m1/ldap-codec/src/main/java/org/apache/directory/shared/ldap/codec/standalone/StandaloneLdapCodecService.java (added) +++ directory/shared/branches/m1/ldap-codec/src/main/java/org/apache/directory/shared/ldap/codec/standalone/StandaloneLdapCodecService.java Thu Feb 10 03:36:27 2011 @@ -0,0 +1,698 @@ +/* + * 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.ExtendedOpFactory; +import org.apache.directory.shared.ldap.codec.api.LdapCodecService; +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.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 Apache Directory Project + * @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> controlFactories = new HashMap>(); + + /** The map of registered {@link org.apache.directory.shared.ldap.codec.api.ExtendedOpFactory}'s by request OID */ + private Map> extReqFactories = new HashMap>(); + + /** The map of registered {@link ExtendedOpFactory}'s by response OID */ + private Map> extResFactories = new HashMap>(); + + /** 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: + *
+     *   <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>
+     * 
+ */ + 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 org.osgi.framework.system.packages.extra 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 activators = new ArrayList(); + activators.add( activator ); + + // setup configuration for felix + Map config = new HashMap(); + 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 void registerControl( ControlFactory factory ) + { + controlFactories.put( factory.getOid(), factory ); + } + + + /** + * {@inheritDoc} + */ + public void unregisterControl( String oid ) + { + controlFactories.remove( oid ); + } + + + /** + * {@inheritDoc} + */ + public Iterator registeredControls() + { + return Collections.unmodifiableSet( controlFactories.keySet() ).iterator(); + } + + + /** + * {@inheritDoc} + */ + public boolean isControlRegistered( String oid ) + { + return controlFactories.containsKey( oid ); + } + + + /** + * {@inheritDoc} + */ + public Iterator registeredExtendedRequests() + { + return Collections.unmodifiableSet( extReqFactories.keySet() ).iterator(); + } + + + /** + * {@inheritDoc} + */ + public Iterator registeredExtendedResponses() + { + return Collections.unmodifiableSet( extResFactories.keySet() ).iterator(); + } + + + /** + * {@inheritDoc} + */ + public void registerExtendedOp( ExtendedOpFactory factory ) + { + extReqFactories.put( factory.getRequestOid(), 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(); + } + 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 newControl( String oid ) + { + ControlFactory factory = controlFactories.get( oid ); + + if ( factory == null ) + { + return new BasicControlDecorator( this, new OpaqueControl( oid ) ); + } + + return factory.newCodecControl(); + } + + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public CodecControl 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( this, control ); + } + + return factory.newCodecControl( control ); + } + + + /** + * {@inheritDoc} + */ + public javax.naming.ldap.Control toJndiControl( Control control ) throws EncoderException + { + CodecControl 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 decorator = + new BasicControlDecorator( this, ourControl ); + decorator.setValue( control.getEncodedValue() ); + return decorator; + } + + @SuppressWarnings("unchecked") + CodecControl ourControl = factory.newCodecControl(); + ourControl.setCritical( control.isCritical() ); + ourControl.setValue( control.getEncodedValue() ); + ourControl.decode( control.getEncodedValue() ); + return ourControl; + } + + + /** + * {@inheritDoc} + */ + public Asn1Container newMessageContainer() + { + return new LdapMessageContainer>( 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; + } +}