You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2006/10/12 20:33:19 UTC
svn commit: r463366 [2/5] - in /directory/trunks/apacheds/mitosis/src: ./
main/ main/java/ main/java/org/ main/java/org/apache/
main/java/org/apache/directory/ main/java/org/apache/directory/mitosis/
main/java/org/apache/directory/mitosis/common/ main/...
Added: directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/operation/AttributeOperation.java
URL: http://svn.apache.org/viewvc/directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/operation/AttributeOperation.java?view=auto&rev=463366
==============================================================================
--- directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/operation/AttributeOperation.java (added)
+++ directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/operation/AttributeOperation.java Thu Oct 12 11:33:14 2006
@@ -0,0 +1,95 @@
+/*
+ * 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.mitosis.operation;
+
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+
+import org.apache.directory.server.core.partition.PartitionNexus;
+import org.apache.directory.mitosis.common.CSN;
+import org.apache.directory.mitosis.operation.support.EntryUtil;
+import org.apache.directory.mitosis.store.ReplicationStore;
+
+/**
+ * An {@link Operation} that adds an attribute to an entry.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public abstract class AttributeOperation extends Operation
+{
+ private final Name name;
+ private final Attribute attribute;
+
+ /**
+ * Create a new operation that affects an entry with the specified name.
+ *
+ * @param name the normalized name of an entry
+ * @param attribute an attribute to modify
+ */
+ public AttributeOperation( CSN csn, Name name, Attribute attribute )
+ {
+ super( csn );
+
+ assert name != null;
+ assert attribute != null;
+
+ this.name = name;
+ this.attribute = ( Attribute ) attribute.clone();
+ }
+
+ /**
+ * Returns the attribute to modify.
+ */
+ public Attribute getAttribute()
+ {
+ return ( Attribute ) attribute.clone();
+ }
+
+ /**
+ * Returns the name of an entry this operation will affect.
+ */
+ public Name getName()
+ {
+ return ( Name ) name.clone();
+ }
+
+ protected final void execute0( PartitionNexus nexus, ReplicationStore store ) throws NamingException
+ {
+ if( !EntryUtil.isEntryUpdatable( nexus, name, getCSN() ) )
+ {
+ return;
+ }
+ EntryUtil.createGlueEntries( nexus, name, true );
+
+ execute1( nexus );
+ }
+
+ protected abstract void execute1( PartitionNexus nexus ) throws NamingException;
+
+
+ /**
+ * Returns string representation of this operation.
+ */
+ public String toString()
+ {
+ return super.toString() + ": [" + name.toString() + ']';
+ }
+}
Added: directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/operation/CompositeOperation.java
URL: http://svn.apache.org/viewvc/directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/operation/CompositeOperation.java?view=auto&rev=463366
==============================================================================
--- directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/operation/CompositeOperation.java (added)
+++ directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/operation/CompositeOperation.java Thu Oct 12 11:33:14 2006
@@ -0,0 +1,142 @@
+/*
+ * 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.mitosis.operation;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import javax.naming.Name;
+import javax.naming.NamingException;
+
+import org.apache.directory.server.core.DirectoryServiceConfiguration;
+import org.apache.directory.server.core.partition.PartitionNexus;
+import org.apache.directory.mitosis.common.CSN;
+import org.apache.directory.mitosis.common.CSNVector;
+import org.apache.directory.mitosis.common.ReplicaId;
+import org.apache.directory.mitosis.common.UUID;
+import org.apache.directory.mitosis.configuration.ReplicationConfiguration;
+import org.apache.directory.mitosis.store.ReplicationLogIterator;
+import org.apache.directory.mitosis.store.ReplicationStore;
+
+/**
+ * An {@link Operation} that contains other {@link Operation}s.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class CompositeOperation extends Operation
+{
+ private static final long serialVersionUID = 6252675003841951356L;
+
+ private static final ReplicationStore DUMMY_STORE = new ReplicationStore() {
+
+ public void open( DirectoryServiceConfiguration serviceCfg, ReplicationConfiguration cfg) {
+ }
+
+ public void close() {
+ }
+
+ public ReplicaId getReplicaId() {
+ return null;
+ }
+
+ public Set getKnownReplicaIds() {
+ return null;
+ }
+
+ public Name getDN(UUID uuid) {
+ return null;
+ }
+
+ public boolean putUUID(UUID uuid, Name dn) {
+ return false;
+ }
+
+ public boolean removeUUID(UUID uuid) {
+ return false;
+ }
+
+ public void putLog(Operation operation) {
+ }
+
+ public ReplicationLogIterator getLogs(CSN fromCSN, boolean inclusive) {
+ return null;
+ }
+
+ public ReplicationLogIterator getLogs(CSNVector updateVector, boolean inclusive) {
+ return null;
+ }
+
+ public int removeLogs(CSN toCSN, boolean inclusive) {
+ return 0;
+ }
+
+ public int getLogSize() {
+ return 0;
+ }
+
+ public int getLogSize(ReplicaId replicaId) {
+ return 0;
+ }
+
+ public CSNVector getUpdateVector() {
+ return null;
+ }
+
+ public CSNVector getPurgeVector() {
+ return null;
+ }
+ };
+
+ private final List children = new ArrayList();
+
+ public CompositeOperation( CSN csn )
+ {
+ super( csn );
+ }
+
+ public void add( Operation op )
+ {
+ assert op != null;
+ assert op.getCSN().equals( this.getCSN() );
+ children.add( op );
+ }
+
+ public void clear()
+ {
+ children.clear();
+ }
+
+ protected void execute0( PartitionNexus nexus, ReplicationStore store ) throws NamingException
+ {
+ Iterator i = children.iterator();
+ while( i.hasNext() )
+ {
+ Operation op = ( Operation ) i.next();
+ op.execute( nexus, DUMMY_STORE );
+ }
+ }
+
+ public String toString()
+ {
+ return children.toString();
+ }
+}
Added: directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/operation/DeleteAttributeOperation.java
URL: http://svn.apache.org/viewvc/directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/operation/DeleteAttributeOperation.java?view=auto&rev=463366
==============================================================================
--- directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/operation/DeleteAttributeOperation.java (added)
+++ directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/operation/DeleteAttributeOperation.java Thu Oct 12 11:33:14 2006
@@ -0,0 +1,63 @@
+/*
+ * 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.mitosis.operation;
+
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttributes;
+import javax.naming.directory.DirContext;
+
+import org.apache.directory.server.core.partition.PartitionNexus;
+import org.apache.directory.shared.ldap.name.LdapDN;
+import org.apache.directory.mitosis.common.CSN;
+
+/**
+ * An {@link Operation} that deletes an attribute from an entry.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class DeleteAttributeOperation extends AttributeOperation
+{
+ private static final long serialVersionUID = -131557844165710365L;
+
+ /**
+ * Creates a new operation that deletes the specified attribute.
+ *
+ * @param attribute an attribute to delete
+ */
+ public DeleteAttributeOperation( CSN csn, Name name, Attribute attribute )
+ {
+ super( csn, name, attribute );
+ }
+
+ public String toString()
+ {
+ return super.toString() + ".delete( " + getAttribute() + " )";
+ }
+
+ protected void execute1( PartitionNexus nexus ) throws NamingException
+ {
+ Attributes attrs = new BasicAttributes();
+ attrs.put( getAttribute() );
+ nexus.modify( (LdapDN)getName(), DirContext.REMOVE_ATTRIBUTE, attrs );
+ }
+}
Added: directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/operation/Operation.java
URL: http://svn.apache.org/viewvc/directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/operation/Operation.java?view=auto&rev=463366
==============================================================================
--- directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/operation/Operation.java (added)
+++ directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/operation/Operation.java Thu Oct 12 11:33:14 2006
@@ -0,0 +1,94 @@
+/*
+ * 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.mitosis.operation;
+
+import java.io.Serializable;
+
+import javax.naming.NamingException;
+import javax.naming.OperationNotSupportedException;
+
+import org.apache.directory.server.core.partition.PartitionNexus;
+import org.apache.directory.mitosis.common.CSN;
+import org.apache.directory.mitosis.store.ReplicationStore;
+
+/**
+ * Represents a small operation on an entry in replicated {@link DirectoryPartition}.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class Operation implements Serializable
+{
+ /**
+ * Declares the Serial Version Uid.
+ *
+ * @see <a
+ * href="http://c2.com/cgi/wiki?AlwaysDeclareSerialVersionUid">Always
+ * Declare Serial Version Uid</a>
+ */
+ private static final long serialVersionUID = 1L;
+
+ /** The entry CSN */
+ private CSN csn;
+
+ /**
+ * Creates a new instance of Operation, for the entry which
+ * csn is given as a parameter.
+ *
+ * @param csn The entry's csn.
+ */
+ public Operation( CSN csn )
+ {
+ assert csn != null;
+ this.csn = csn;
+ }
+
+ /**
+ * @return Returns {@link CSN} for this operation.
+ */
+ public CSN getCSN()
+ {
+ return csn;
+ }
+
+ /**
+ * @return the CSN for this operation
+ */
+ public String toString()
+ {
+ return csn.toString();
+ }
+
+ /**
+ * Exeutes this operation on the specified nexus.
+ */
+ public final void execute( PartitionNexus nexus, ReplicationStore store ) throws NamingException
+ {
+ synchronized( nexus )
+ {
+ execute0( nexus, store );
+ store.putLog( this );
+ }
+ }
+
+ protected void execute0( PartitionNexus nexus, ReplicationStore store ) throws NamingException
+ {
+ throw new OperationNotSupportedException( nexus.getSuffix().toString() );
+ }
+}
Added: directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/operation/OperationCodec.java
URL: http://svn.apache.org/viewvc/directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/operation/OperationCodec.java?view=auto&rev=463366
==============================================================================
--- directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/operation/OperationCodec.java (added)
+++ directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/operation/OperationCodec.java Thu Oct 12 11:33:14 2006
@@ -0,0 +1,76 @@
+/*
+ * 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.mitosis.operation;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamConstants;
+
+/**
+ * Encodes {@link Operation}s to <tt>byte[]</tt> and vice versa.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class OperationCodec
+{
+ public OperationCodec()
+ {
+ }
+
+ public byte[] encode( Operation op )
+ {
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ try
+ {
+ ObjectOutputStream out = new ObjectOutputStream( bout );
+ out.useProtocolVersion( ObjectStreamConstants.PROTOCOL_VERSION_2 );
+ out.writeObject( op );
+ out.flush();
+ out.close();
+ }
+ catch( IOException e )
+ {
+ throw ( InternalError ) new InternalError().initCause( e );
+ }
+ return bout.toByteArray();
+ }
+
+ public Operation decode( byte[] data )
+ {
+ ObjectInputStream in;
+ try
+ {
+ in = new ObjectInputStream(
+ new ByteArrayInputStream( data ) );
+ return ( Operation ) in.readObject();
+ }
+ catch( IOException e )
+ {
+ throw ( InternalError ) new InternalError().initCause( e );
+ }
+ catch( ClassNotFoundException e )
+ {
+ throw ( InternalError ) new InternalError().initCause( e );
+ }
+ }
+}
Added: directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/operation/OperationFactory.java
URL: http://svn.apache.org/viewvc/directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/operation/OperationFactory.java?view=auto&rev=463366
==============================================================================
--- directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/operation/OperationFactory.java (added)
+++ directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/operation/OperationFactory.java Thu Oct 12 11:33:14 2006
@@ -0,0 +1,286 @@
+/*
+ * 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.mitosis.operation;
+
+import java.util.Map;
+
+import javax.naming.Name;
+import javax.naming.NameAlreadyBoundException;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.OperationNotSupportedException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttribute;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.ModificationItem;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+
+import org.apache.directory.server.core.DirectoryServiceConfiguration;
+import org.apache.directory.server.core.partition.PartitionNexus;
+import org.apache.directory.shared.ldap.filter.PresenceNode;
+import org.apache.directory.shared.ldap.name.LdapDN;
+import org.apache.directory.shared.ldap.util.NamespaceTools;
+import org.apache.directory.mitosis.common.CSN;
+import org.apache.directory.mitosis.common.CSNFactory;
+import org.apache.directory.mitosis.common.Constants;
+import org.apache.directory.mitosis.common.ReplicaId;
+import org.apache.directory.mitosis.common.UUIDFactory;
+import org.apache.directory.mitosis.configuration.ReplicationConfiguration;
+
+/**
+ * Converts a complex JNDI operations into multiple simple operations.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class OperationFactory
+{
+ private final ReplicaId replicaId;
+ private final Map environment;
+ private final PartitionNexus nexus;
+ private final UUIDFactory uuidFactory;
+ private final CSNFactory csnFactory;
+
+ public OperationFactory( DirectoryServiceConfiguration serviceCfg, ReplicationConfiguration cfg )
+ {
+ this.replicaId = cfg.getReplicaId();
+ this.environment = serviceCfg.getEnvironment();
+ this.nexus = serviceCfg.getPartitionNexus();
+ this.uuidFactory = cfg.getUuidFactory();
+ this.csnFactory = cfg.getCsnFactory();
+ }
+
+ public Operation newAdd( String userProvidedName, Name normalizedName, Attributes entry ) throws NamingException
+ {
+ return newAdd( newCSN(), userProvidedName, normalizedName, entry );
+ }
+
+ private Operation newAdd( CSN csn, String userProvidedName, Name normalizedName, Attributes entry ) throws NamingException
+ {
+ // Check an entry already exists.
+ checkBeforeAdd( normalizedName );
+
+ CompositeOperation result = new CompositeOperation( csn );
+
+ // Insert 'entryUUID' and 'entryDeleted'.
+ entry = ( Attributes ) entry.clone();
+ entry.remove( Constants.ENTRY_UUID );
+ entry.remove( Constants.ENTRY_DELETED );
+ entry.put( Constants.ENTRY_UUID, uuidFactory.newInstance().toOctetString() );
+ entry.put( Constants.ENTRY_DELETED, "false" );
+
+ // NOTE: We inlined addDefaultOperations() because ApacheDS currently
+ // creates an index entry only for ADD operation (and not for
+ // MODIFY operation)
+ entry.put( Constants.ENTRY_CSN, csn.toOctetString() );
+
+ result.add( new AddEntryOperation( csn, normalizedName, userProvidedName, entry ) );
+ return result;
+ }
+
+ public Operation newDelete( Name normalizedName )
+ {
+ CSN csn = newCSN();
+ CompositeOperation result = new CompositeOperation( csn );
+
+ // Transform into replace operation.
+ result.add(
+ new ReplaceAttributeOperation(
+ csn,
+ normalizedName,
+ new BasicAttribute( Constants.ENTRY_DELETED, "true" ) ) );
+
+ return addDefaultOperations( result, csn, normalizedName );
+ }
+
+ public Operation newModify( Name normalizedName, int modOp, Attributes attributes )
+ {
+ CSN csn = newCSN();
+ CompositeOperation result = new CompositeOperation( csn );
+ NamingEnumeration e = attributes.getAll();
+ // Transform into multiple {@link AttributeOperation}s.
+ while( e.hasMoreElements() )
+ {
+ Attribute attr = ( Attribute ) e.nextElement();
+ result.add( newModify( csn, normalizedName, modOp, attr ) );
+ }
+
+ // Resurrect the entry in case it is deleted.
+ result.add(
+ new ReplaceAttributeOperation(
+ csn,
+ normalizedName,
+ new BasicAttribute( Constants.ENTRY_DELETED, "false" ) ) );
+
+ return addDefaultOperations( result, null, normalizedName );
+ }
+
+ public Operation newModify( Name normalizedName, ModificationItem[] items )
+ {
+ CSN csn = newCSN();
+ CompositeOperation result = new CompositeOperation( csn );
+ final int length = items.length;
+ // Transform into multiple {@link AttributeOperation}s.
+ for( int i = 0; i < length; i ++ )
+ {
+ ModificationItem item = items[ i ];
+ result.add(
+ newModify(
+ csn,
+ normalizedName,
+ item.getModificationOp(),
+ item.getAttribute() ) );
+ }
+
+ // Resurrect the entry in case it is deleted.
+ result.add(
+ new ReplaceAttributeOperation(
+ csn,
+ normalizedName,
+ new BasicAttribute( Constants.ENTRY_DELETED, "false" ) ) );
+
+ return addDefaultOperations( result, csn, normalizedName );
+ }
+
+ private Operation newModify( CSN csn, Name normalizedName, int modOp, Attribute attribute )
+ {
+ switch( modOp )
+ {
+ case DirContext.ADD_ATTRIBUTE:
+ return new AddAttributeOperation(
+ csn,
+ normalizedName,
+ attribute );
+ case DirContext.REPLACE_ATTRIBUTE:
+ return new ReplaceAttributeOperation(
+ csn,
+ normalizedName,
+ attribute );
+ case DirContext.REMOVE_ATTRIBUTE:
+ return new DeleteAttributeOperation(
+ csn,
+ normalizedName,
+ attribute );
+ default:
+ throw new IllegalArgumentException( "Unknown modOp: " + modOp );
+ }
+ }
+
+ public Operation newModifyRn( Name oldName, String newRdn, boolean deleteOldRn ) throws NamingException
+ {
+ return newMove( oldName, oldName.getSuffix( 1 ), newRdn, deleteOldRn );
+ }
+
+ public Operation newMove( Name oldName, Name newParentName ) throws NamingException
+ {
+ return newMove( oldName, newParentName, oldName.get( oldName.size() - 1 ), true );
+ }
+
+ public Operation newMove( Name oldName, Name newParentName, String newRdn, boolean deleteOldRn ) throws NamingException
+ {
+ if( !deleteOldRn )
+ {
+ throw new OperationNotSupportedException( "deleteOldRn must be true." );
+ }
+
+ // Prepare to create composite operations
+ CSN csn = newCSN();
+ CompositeOperation result = new CompositeOperation( csn );
+
+ // Retrieve all subtree including the base entry
+ SearchControls ctrl = new SearchControls();
+ ctrl.setSearchScope( SearchControls.SUBTREE_SCOPE );
+ NamingEnumeration e = nexus.search(
+ (LdapDN)oldName, environment, new PresenceNode( "objectClass" ), ctrl );
+
+ while( e.hasMore() )
+ {
+ SearchResult sr = ( SearchResult ) e.next();
+
+ // Get the name of the old entry
+ Name oldEntryName = new LdapDN( sr.getName() );
+
+ // Delete the old entry
+ result.add(
+ new ReplaceAttributeOperation(
+ csn,
+ oldEntryName,
+ new BasicAttribute( Constants.ENTRY_DELETED, "true" ) ) );
+
+ // Get the old entry attributes and replace RDN if required
+ Attributes entry = sr.getAttributes();
+ if( oldEntryName.size() == oldName.size() )
+ {
+ entry.remove(
+ NamespaceTools.getRdnAttribute(
+ oldName.get( oldName.size() - 1 ) ) );
+ entry.put(
+ NamespaceTools.getRdnAttribute( newRdn ),
+ NamespaceTools.getRdnValue( newRdn ) );
+ }
+
+ // Calculate new name from newParentName, oldEntryName, and newRdn.
+ Name newEntryName = ( Name ) newParentName.clone();
+ newEntryName.add( newRdn );
+ for( int i = oldEntryName.size() - newEntryName.size(); i > 0; i-- )
+ {
+ newEntryName.add( oldEntryName.get( oldEntryName.size() - i ) );
+ }
+
+ // Add the new entry
+ //// FIXME Get UPDN somehow
+ result.add( newAdd( csn, newEntryName.toString(), newEntryName, entry ) );
+
+ // Add default operations to the old entry.
+ // Please note that newAdd() already added default operations
+ // to the new entry.
+ addDefaultOperations( result, csn, oldEntryName );
+ }
+
+ return result;
+ }
+
+ private void checkBeforeAdd( Name newEntryName ) throws NamingException
+ {
+ if( nexus.hasEntry( (LdapDN)newEntryName ) )
+ {
+ throw new NameAlreadyBoundException( newEntryName.toString() + " already exists." );
+ }
+ }
+
+ private CompositeOperation addDefaultOperations( CompositeOperation result, CSN csn, Name normalizedName )
+ {
+ result.add(
+ new ReplaceAttributeOperation(
+ csn,
+ normalizedName,
+ new BasicAttribute(
+ Constants.ENTRY_CSN,
+ csn.toOctetString()) ) );
+ return result;
+ }
+
+ private CSN newCSN()
+ {
+ return csnFactory.newInstance( replicaId );
+ }
+
+}
Added: directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/operation/ReplaceAttributeOperation.java
URL: http://svn.apache.org/viewvc/directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/operation/ReplaceAttributeOperation.java?view=auto&rev=463366
==============================================================================
--- directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/operation/ReplaceAttributeOperation.java (added)
+++ directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/operation/ReplaceAttributeOperation.java Thu Oct 12 11:33:14 2006
@@ -0,0 +1,63 @@
+/*
+ * 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.mitosis.operation;
+
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttributes;
+import javax.naming.directory.DirContext;
+
+import org.apache.directory.server.core.partition.PartitionNexus;
+import org.apache.directory.shared.ldap.name.LdapDN;
+import org.apache.directory.mitosis.common.CSN;
+
+/**
+ * An {@link Operation} that replaces an attribute in an entry.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class ReplaceAttributeOperation extends AttributeOperation
+{
+ private static final long serialVersionUID = -6573196586521610472L;
+
+ /**
+ * Creates a new operation that replaces the specified attribute.
+ *
+ * @param attribute an attribute to replace
+ */
+ public ReplaceAttributeOperation( CSN csn, Name name, Attribute attribute )
+ {
+ super( csn, name, attribute );
+ }
+
+ public String toString()
+ {
+ return super.toString() + ".replace( " + getAttribute() + " )";
+ }
+
+ protected void execute1( PartitionNexus nexus ) throws NamingException
+ {
+ Attributes attrs = new BasicAttributes();
+ attrs.put( getAttribute() );
+ nexus.modify( (LdapDN)getName(), DirContext.REPLACE_ATTRIBUTE, attrs );
+ }
+}
Added: directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/operation/support/EntryUtil.java
URL: http://svn.apache.org/viewvc/directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/operation/support/EntryUtil.java?view=auto&rev=463366
==============================================================================
--- directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/operation/support/EntryUtil.java (added)
+++ directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/operation/support/EntryUtil.java Thu Oct 12 11:33:14 2006
@@ -0,0 +1,121 @@
+/*
+ * 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.mitosis.operation.support;
+
+import javax.naming.Name;
+import javax.naming.NameNotFoundException;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttribute;
+import javax.naming.directory.BasicAttributes;
+
+import org.apache.directory.server.core.partition.PartitionNexus;
+import org.apache.directory.shared.ldap.name.LdapDN;
+import org.apache.directory.shared.ldap.util.NamespaceTools;
+import org.apache.directory.mitosis.common.CSN;
+import org.apache.directory.mitosis.common.Constants;
+import org.apache.directory.mitosis.common.SimpleCSN;
+
+public class EntryUtil
+{
+ public static boolean isEntryUpdatable( PartitionNexus nexus, Name name, CSN newCSN ) throws NamingException
+ {
+ Attributes entry = nexus.lookup( (LdapDN)name );
+
+ if( entry == null )
+ {
+ return true;
+ }
+
+ Attribute entryCSNAttr = entry.get( Constants.ENTRY_CSN );
+
+ if( entryCSNAttr == null )
+ {
+ return true;
+ }
+ else
+ {
+ CSN oldCSN = null;
+
+ try
+ {
+ oldCSN = new SimpleCSN( String.valueOf( entryCSNAttr.get() ) );
+ }
+ catch( IllegalArgumentException e )
+ {
+ return true;
+ }
+
+ return oldCSN.compareTo( newCSN ) < 0;
+ }
+ }
+
+ public static void createGlueEntries( PartitionNexus nexus, Name name, boolean includeLeaf ) throws NamingException
+ {
+ assert name.size() > 0;
+
+ for( int i = name.size() - 1; i > 0; i -- )
+ {
+ createGlueEntry( nexus, name.getSuffix( i ) );
+ }
+
+ if( includeLeaf )
+ {
+ createGlueEntry( nexus, name );
+ }
+ }
+
+ private static void createGlueEntry( PartitionNexus nexus, Name name ) throws NamingException
+ {
+ try
+ {
+ if( nexus.hasEntry( (LdapDN)name ) )
+ {
+ return;
+ }
+ }
+ catch( NameNotFoundException e )
+ {
+ // Skip if there's no backend associated with the name.
+ return;
+ }
+
+ // Create a glue entry.
+ Attributes entry = new BasicAttributes();
+ //// Add RDN attribute.
+ String rdn = name.get( name.size() - 1 );
+ String rdnAttribute = NamespaceTools.getRdnAttribute( rdn );
+ String rdnValue = NamespaceTools.getRdnValue( rdn );
+ entry.put( rdnAttribute, rdnValue );
+ //// Add objectClass attribute.
+ Attribute objectClassAttr = new BasicAttribute( "objectClass" );
+ objectClassAttr.add( "top" );
+ objectClassAttr.add( "extensibleObject" );
+ entry.put( objectClassAttr );
+
+ // And add it to the nexus.
+ nexus.add( (LdapDN)name, entry );
+ }
+
+ private EntryUtil()
+ {
+ }
+}
Added: directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/ClientConnectionManager.java
URL: http://svn.apache.org/viewvc/directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/ClientConnectionManager.java?view=auto&rev=463366
==============================================================================
--- directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/ClientConnectionManager.java (added)
+++ directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/ClientConnectionManager.java Thu Oct 12 11:33:14 2006
@@ -0,0 +1,308 @@
+/*
+ * 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.mitosis.service;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.mina.common.ConnectFuture;
+import org.apache.mina.common.IoConnector;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.LoggingFilter;
+import org.apache.mina.filter.thread.ThreadPoolFilter;
+import org.apache.mina.transport.socket.nio.SocketConnector;
+import org.apache.directory.mitosis.common.Replica;
+import org.apache.directory.mitosis.configuration.ReplicationConfiguration;
+import org.apache.directory.mitosis.service.protocol.handler.ReplicationClientProtocolHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Manages all outgoing connections to remote replicas.
+ *
+ * @author Trustin Lee
+ * @version $Rev: 116 $, $Date: 2006-09-18 13:47:53Z $
+ */
+class ClientConnectionManager
+{
+ private static final Logger log = LoggerFactory.getLogger( ClientConnectionManager.class );
+
+ private final ReplicationService service;
+ private final IoConnector connector = new SocketConnector();
+ private final Map sessions = new HashMap();
+ private ReplicationConfiguration configuration;
+ private ConnectionMonitor monitor;
+
+ ClientConnectionManager( ReplicationService service )
+ {
+ this.service = service;
+ }
+
+ public void start( ReplicationConfiguration cfg ) throws Exception
+ {
+ // initialze client connection
+ //// initialize thread pool
+ ThreadPoolFilter threadPoolFilter = new ThreadPoolFilter();
+ connector.getFilterChain().addLast( "threadPool", threadPoolFilter );
+ //// add logger
+ connector.getFilterChain().addLast( "logger", new LoggingFilter() );
+
+ this.configuration = cfg;
+
+ monitor = new ConnectionMonitor();
+ monitor.start();
+ }
+
+ public void stop() throws Exception
+ {
+ // close all connections
+ monitor.shutdown();
+
+ // remove all filters
+ connector.getFilterChain().remove( "threadPool" );
+ connector.getFilterChain().remove( "logger" );
+ }
+
+ private class ConnectionMonitor extends Thread
+ {
+ private boolean timeToShutdown = false;
+
+ public ConnectionMonitor()
+ {
+ super( "ClientConnectionManager" );
+ }
+
+ public void shutdown()
+ {
+ timeToShutdown = true;
+ while( isAlive() )
+ {
+ try
+ {
+ join();
+ }
+ catch( InterruptedException e )
+ {
+ log.warn( "Unexpected exception.", e );
+ }
+ }
+ }
+
+ public void run()
+ {
+ while( !timeToShutdown )
+ {
+ connectUnconnected();
+ try
+ {
+ Thread.sleep( 1000 );
+ }
+ catch( InterruptedException e )
+ {
+ log.warn( "Unexpected exception.", e );
+ }
+ }
+
+ disconnectConnected();
+ }
+
+ private void connectUnconnected()
+ {
+ Iterator i = configuration.getPeerReplicas().iterator();
+ while( i.hasNext() )
+ {
+ Replica replica = ( Replica ) i.next();
+ Connection con = ( Connection ) sessions.get( replica.getId() );
+ if( con == null )
+ {
+ con = new Connection();
+ sessions.put( replica.getId(), con );
+ }
+
+ synchronized( con )
+ {
+ if( con.inProgress )
+ {
+ // connection is in progress
+ continue;
+ }
+
+ if( con.session != null )
+ {
+ if( con.session.isConnected() )
+ {
+ continue;
+ }
+ con.session = null;
+ }
+
+ // put to connectingSession with dummy value to mark
+ // that connection is in progress
+ con.inProgress = true;
+
+ if( con.delay < 0 )
+ {
+ con.delay = 0;
+ }
+ else if( con.delay == 0 )
+ {
+ con.delay = 2;
+ }
+ else
+ {
+ con.delay *= 2;
+ if( con.delay > 60 )
+ {
+ con.delay = 60;
+ }
+ }
+ }
+
+ Connector connector = new Connector( replica, con );
+ synchronized( con )
+ {
+ con.connector = connector;
+ }
+ connector.start();
+ }
+ }
+
+ private void disconnectConnected()
+ {
+ log.info( "Closing all connections..." );
+ for( ;; )
+ {
+ Iterator i = sessions.values().iterator();
+ while( i.hasNext() )
+ {
+ Connection con = ( Connection ) i.next();
+ synchronized( con )
+ {
+ if( con.inProgress )
+ {
+ if( con.connector != null )
+ {
+ con.connector.interrupt();
+ }
+ continue;
+ }
+
+ i.remove();
+
+ if( con.session != null )
+ {
+ con.session.close();
+ }
+ }
+ }
+
+ if( sessions.isEmpty() )
+ {
+ break;
+ }
+
+ // Sleep 1 second and try again waiting for Connector threads.
+ try
+ {
+ Thread.sleep( 1000 );
+ }
+ catch( InterruptedException e )
+ {
+ log.warn( "Unexpected exception.", e );
+ }
+ }
+ }
+ }
+
+ private class Connector extends Thread
+ {
+ private final Replica replica;
+ private final Connection con;
+
+ public Connector( Replica replica, Connection con )
+ {
+ super( "ClientConnectionManager-" + replica );
+ this.replica = replica;
+ this.con = con;
+ }
+
+ public void run()
+ {
+ if( con.delay > 0 )
+ {
+ log.info( "[" + replica + "] Waiting for " + con.delay + " seconds to reconnect." );
+ try
+ {
+ Thread.sleep( con.delay * 1000L );
+ }
+ catch( InterruptedException e )
+ {
+ }
+ }
+
+ log.info( "[" + replica + "] Connecting..." );
+
+ IoSession session;
+ try
+ {
+ connector.setConnectTimeout( configuration.getResponseTimeout() );
+ ConnectFuture future = connector.connect(
+ replica.getAddress(),
+ new ReplicationClientProtocolHandler( service ) );
+
+ future.join();
+ session = future.getSession();
+
+ synchronized( con )
+ {
+ con.session = session;
+ con.delay = -1; // reset delay
+ con.inProgress = false;
+ }
+ }
+ catch( IOException e )
+ {
+ log.warn("[" + replica + "] Failed to connect.", e );
+ }
+ finally
+ {
+ synchronized( con )
+ {
+ con.inProgress = false;
+ con.connector = null;
+ }
+ }
+ }
+ }
+
+ private static class Connection
+ {
+ private IoSession session;
+ private int delay = -1;
+ private boolean inProgress;
+ private Connector connector;
+
+ public Connection()
+ {
+ }
+ }
+}
Added: directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/ReplicationContext.java
URL: http://svn.apache.org/viewvc/directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/ReplicationContext.java?view=auto&rev=463366
==============================================================================
--- directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/ReplicationContext.java (added)
+++ directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/ReplicationContext.java Thu Oct 12 11:33:14 2006
@@ -0,0 +1,69 @@
+/*
+ * 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.mitosis.service;
+
+import org.apache.directory.server.core.DirectoryServiceConfiguration;
+import org.apache.mina.common.IoSession;
+import org.apache.directory.mitosis.common.Replica;
+import org.apache.directory.mitosis.configuration.ReplicationConfiguration;
+
+public interface ReplicationContext {
+ IoSession getSession();
+ ReplicationConfiguration getConfiguration();
+ ReplicationService getService();
+ DirectoryServiceConfiguration getServiceConfiguration();
+ int getNextSequence();
+
+ Replica getPeer();
+ void setPeer( Replica peer );
+
+ State getState();
+ void setState( State state );
+
+ void scheduleExpiration( Object message );
+ Object cancelExpiration( int sequence );
+ void cancelAllExpirations();
+ int getScheduledExpirations();
+
+ public static class State
+ {
+ /**
+ * Connection is established.
+ */
+ public static final State INIT = new State( "INIT" );
+
+ /**
+ * Client has logged in and is ready to exchange information.
+ */
+ public static final State READY = new State( "READY" );
+
+ private final String value;
+
+ private State( String value )
+ {
+ this.value = value;
+ }
+
+ public String toString()
+ {
+ return value;
+ }
+ }
+}
Added: directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/ReplicationLogCleanJob.java
URL: http://svn.apache.org/viewvc/directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/ReplicationLogCleanJob.java?view=auto&rev=463366
==============================================================================
--- directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/ReplicationLogCleanJob.java (added)
+++ directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/ReplicationLogCleanJob.java Thu Oct 12 11:33:14 2006
@@ -0,0 +1,81 @@
+/*
+ * 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.mitosis.service;
+
+import java.util.Iterator;
+
+import javax.naming.NamingException;
+
+import org.apache.directory.server.core.DirectoryService;
+import org.apache.directory.server.core.interceptor.Interceptor;
+import org.quartz.Job;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+
+public class ReplicationLogCleanJob implements Job
+{
+ public static final String INSTANCE_ID = "instanceId";
+
+ public ReplicationLogCleanJob()
+ {
+ }
+
+ public void execute( JobExecutionContext ctx ) throws JobExecutionException
+ {
+ String instanceId = ctx.getJobDetail().getJobDataMap().getString( INSTANCE_ID );
+ if( instanceId == null )
+ {
+ // Execute for all instances in the VM if instanceId is not specified.
+ Iterator it = DirectoryService.getAllInstances().iterator();
+ while( it.hasNext() )
+ {
+ DirectoryService service = ( DirectoryService ) it.next();
+ execute0( service.getConfiguration().getInstanceId() );
+ }
+ }
+ else
+ {
+ // Execute for the instance with the specified instanceId if
+ // it is specified.
+ execute0( instanceId );
+ }
+ }
+
+ private void execute0( String instanceId ) throws JobExecutionException
+ {
+ DirectoryService service = DirectoryService.getInstance( instanceId );
+ Iterator it = service.getConfiguration().getInterceptorChain().getAll().iterator();
+ while( it.hasNext() )
+ {
+ Interceptor interceptor = (Interceptor) it.next();
+ if( interceptor instanceof ReplicationService )
+ {
+ try
+ {
+ ( ( ReplicationService ) interceptor ).purgeAgedData();
+ }
+ catch( NamingException e )
+ {
+ throw new JobExecutionException( e );
+ }
+ }
+ }
+ }
+}
Added: directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/ReplicationService.java
URL: http://svn.apache.org/viewvc/directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/ReplicationService.java?view=auto&rev=463366
==============================================================================
--- directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/ReplicationService.java (added)
+++ directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/ReplicationService.java Thu Oct 12 11:33:14 2006
@@ -0,0 +1,416 @@
+/*
+ * 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.mitosis.service;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.SocketAddress;
+import java.nio.channels.ServerSocketChannel;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.naming.Name;
+import javax.naming.NameNotFoundException;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.ModificationItem;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+
+import org.apache.directory.server.core.DirectoryServiceConfiguration;
+import org.apache.directory.server.core.configuration.InterceptorConfiguration;
+import org.apache.directory.server.core.enumeration.SearchResultFilteringEnumeration;
+import org.apache.directory.server.core.interceptor.BaseInterceptor;
+import org.apache.directory.server.core.interceptor.NextInterceptor;
+import org.apache.directory.server.core.invocation.InvocationStack;
+import org.apache.directory.server.core.partition.PartitionNexus;
+import org.apache.directory.shared.ldap.exception.LdapNameNotFoundException;
+import org.apache.directory.shared.ldap.filter.ExprNode;
+import org.apache.directory.shared.ldap.filter.FilterParser;
+import org.apache.directory.shared.ldap.filter.FilterParserImpl;
+import org.apache.directory.shared.ldap.name.LdapDN;
+import org.apache.mina.common.IoAcceptor;
+import org.apache.mina.common.IoServiceConfig;
+import org.apache.mina.common.TransportType;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+import org.apache.mina.transport.socket.nio.SocketAcceptor;
+import org.apache.mina.transport.socket.nio.SocketAcceptorConfig;
+import org.apache.directory.mitosis.common.CSN;
+import org.apache.directory.mitosis.common.Constants;
+import org.apache.directory.mitosis.common.ReplicaId;
+import org.apache.directory.mitosis.common.SimpleCSN;
+import org.apache.directory.mitosis.configuration.ReplicationConfiguration;
+import org.apache.directory.mitosis.operation.Operation;
+import org.apache.directory.mitosis.operation.OperationFactory;
+import org.apache.directory.mitosis.service.protocol.handler.ReplicationServerProtocolHandler;
+import org.apache.directory.mitosis.store.ReplicationStore;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ReplicationService extends BaseInterceptor
+{
+ private static final Logger log = LoggerFactory.getLogger( ReplicationService.class );
+ private DirectoryServiceConfiguration directoryServiceConfiguration;
+ private ReplicationConfiguration configuration;
+ private PartitionNexus nexus;
+ private OperationFactory operationFactory;
+ private ReplicationStore store;
+ private IoAcceptor registry;
+ private final ClientConnectionManager clientConnectionManager = new ClientConnectionManager( this );
+
+ public ReplicationService()
+ {
+ }
+
+ public ReplicationConfiguration getConfiguration()
+ {
+ return configuration;
+ }
+
+ public void setConfiguration( ReplicationConfiguration cfg )
+ {
+ cfg.validate();
+ this.configuration = cfg;
+ }
+
+ public DirectoryServiceConfiguration getFactoryConfiguration()
+ {
+ return directoryServiceConfiguration;
+ }
+
+ public void init( DirectoryServiceConfiguration serviceCfg, InterceptorConfiguration cfg ) throws NamingException
+ {
+ configuration.validate();
+ // and then preserve frequently used ones
+ directoryServiceConfiguration = serviceCfg;
+ nexus = serviceCfg.getPartitionNexus();
+ store = configuration.getStore();
+ operationFactory = new OperationFactory( serviceCfg, configuration );
+
+ // Initialize store and service
+ store.open( serviceCfg, configuration );
+ boolean serviceStarted = false;
+ try
+ {
+ startNetworking();
+ serviceStarted = true;
+ }
+ catch( Exception e )
+ {
+ throw new ReplicationServiceException( "Failed to initialize MINA ServiceRegistry.", e );
+ }
+ finally
+ {
+ if( !serviceStarted )
+ {
+ // roll back
+ store.close();
+ }
+ }
+
+ purgeAgedData();
+ }
+
+ private void startNetworking() throws Exception
+ {
+ registry = new SocketAcceptor();
+ IoServiceConfig config = new SocketAcceptorConfig();
+
+ config.getFilterChain().addLast( "protocol", new ProtocolCodecFilter( new ReplicationServerProtocolHandler( this ) ) );
+
+ // bind server protocol provider
+ registry.bind( new InetSocketAddress( 10101 ),
+ new ServerHandler( true, new RunnableFactory() ),
+ config );
+
+ clientConnectionManager.start( configuration );
+ }
+
+ public void destroy()
+ {
+ stopNetworking();
+ store.close();
+ }
+
+ private void stopNetworking()
+ {
+ // close all open connections, deactivate all filters and service registry
+ try
+ {
+ clientConnectionManager.stop();
+ }
+ catch( Exception e )
+ {
+ log.warn( "Failed to stop the client connection manager.", e );
+ }
+ registry.unbindAll();
+ }
+
+ public void purgeAgedData() throws NamingException
+ {
+ Attributes rootDSE = nexus.getRootDSE();
+ Attribute namingContextsAttr = rootDSE.get( "namingContexts" );
+ if( namingContextsAttr == null || namingContextsAttr.size() == 0 )
+ {
+ throw new NamingException( "No namingContexts attributes in rootDSE." );
+ }
+
+ CSN purgeCSN = new SimpleCSN(
+ System.currentTimeMillis() -
+ configuration.getLogMaxAge() * 1000L * 60L * 60L * 24L, // convert days to millis
+ new ReplicaId( "ZZZZZZZZZZZZZZZZ" ),
+ Integer.MAX_VALUE );
+ FilterParser parser = new FilterParserImpl();
+ ExprNode filter;
+
+ try
+ {
+ filter = parser.parse(
+ "(& (entryCSN=<" +
+ purgeCSN.toOctetString() +
+ ") (entryDeleted=true))" );
+ }
+ catch( IOException e )
+ {
+ throw ( NamingException ) new NamingException().initCause( e );
+ }
+ catch( ParseException e )
+ {
+ throw ( NamingException ) new NamingException().initCause( e );
+ }
+
+ // Iterate all context partitions to send all entries of them.
+ NamingEnumeration e = namingContextsAttr.getAll();
+ while( e.hasMore() )
+ {
+ Object value = e.next();
+ // Convert attribute value to JNDI name.
+ Name contextName;
+ if( value instanceof Name )
+ {
+ contextName = ( Name ) value;
+ }
+ else
+ {
+ contextName = new LdapDN( String.valueOf( value ) );
+ }
+
+ log.info( "Purging aged data under '" + contextName + '"');
+ purgeAgedData( contextName, filter );
+ }
+
+ store.removeLogs( purgeCSN, false );
+ }
+
+ private void purgeAgedData( Name contextName, ExprNode filter ) throws NamingException
+ {
+ SearchControls ctrl = new SearchControls();
+ ctrl.setSearchScope( SearchControls.SUBTREE_SCOPE );
+ ctrl.setReturningAttributes( new String[]
+ { "entryCSN", "entryDeleted" } );
+
+ NamingEnumeration e = nexus.search(
+ (LdapDN)contextName,
+ directoryServiceConfiguration.getEnvironment(),
+ filter, ctrl );
+
+ List names = new ArrayList();
+ try
+ {
+ while( e.hasMore() )
+ {
+ SearchResult sr = ( SearchResult ) e.next();
+ Name name = new LdapDN( sr.getName() );
+ if( name.size() > contextName.size() )
+ {
+ names.add( new LdapDN( sr.getName() ) );
+ }
+ }
+ }
+ finally
+ {
+ e.close();
+ }
+
+ Iterator it = names.iterator();
+ while( it.hasNext() )
+ {
+ Name name = (Name) it.next();
+ try
+ {
+ Attributes entry = nexus.lookup( (LdapDN)name );
+ log.info( "Purge: " + name + " (" + entry + ')' );
+ nexus.delete( (LdapDN)name );
+ }
+ catch( NamingException ex )
+ {
+ log.warn( "Failed to fetch/delete: " + name, ex );
+ }
+ }
+ }
+
+ public void add( NextInterceptor nextInterceptor, String userProvidedName, Name normalizedName, Attributes entry ) throws NamingException
+ {
+ Operation op = operationFactory.newAdd( userProvidedName, normalizedName, entry );
+ op.execute( nexus, store );
+ }
+
+ public void delete( NextInterceptor nextInterceptor, Name name ) throws NamingException
+ {
+ Operation op = operationFactory.newDelete( name );
+ op.execute( nexus, store );
+ }
+
+ public void modify( NextInterceptor next, Name name, int modOp, Attributes attrs ) throws NamingException
+ {
+ Operation op = operationFactory.newModify( name, modOp, attrs );
+ op.execute( nexus, store );
+ }
+
+ public void modify( NextInterceptor next, Name name, ModificationItem[] items ) throws NamingException
+ {
+ Operation op = operationFactory.newModify( name, items );
+ op.execute( nexus, store );
+ }
+
+ public void modifyRn( NextInterceptor next, Name oldName, String newRDN, boolean deleteOldRDN ) throws NamingException
+ {
+ Operation op = operationFactory.newModifyRn( oldName, newRDN, deleteOldRDN );
+ op.execute( nexus, store );
+ }
+
+ public void move( NextInterceptor next, Name oldName, Name newParentName, String newRDN, boolean deleteOldRDN ) throws NamingException
+ {
+ Operation op = operationFactory.newMove( oldName, newParentName, newRDN, deleteOldRDN );
+ op.execute( nexus, store );
+ }
+
+ public void move( NextInterceptor next, Name oldName, Name newParentName ) throws NamingException
+ {
+ Operation op = operationFactory.newMove( oldName, newParentName );
+ op.execute( nexus, store );
+ }
+
+ public boolean hasEntry( NextInterceptor nextInterceptor, Name name ) throws NamingException
+ {
+ // Ask others first.
+ boolean hasEntry = nextInterceptor.hasEntry( (LdapDN)name );
+
+ // If the entry exists,
+ if( hasEntry )
+ {
+ // Check DELETED attribute.
+ try
+ {
+ Attributes entry = nextInterceptor.lookup( (LdapDN)name );
+ hasEntry = !isDeleted( entry );
+ }
+ catch( NameNotFoundException e )
+ {
+ System.out.println( e.toString( true ) );
+ hasEntry = false;
+ }
+ }
+
+ return hasEntry;
+ }
+
+ public Attributes lookup( NextInterceptor nextInterceptor, Name name ) throws NamingException
+ {
+ Attributes result = nextInterceptor.lookup( (LdapDN)name );
+ ensureNotDeleted( name, result );
+ return result;
+ }
+
+
+ public Attributes lookup( NextInterceptor nextInterceptor, Name name, String[] attrIds ) throws NamingException
+ {
+ boolean found = false;
+ // Look for 'entryDeleted' attribute is in attrIds.
+ for( int i = 0; i < attrIds.length; i ++ )
+ {
+ if( Constants.ENTRY_DELETED.equals( attrIds[i] ) )
+ {
+ found = true;
+ break;
+ }
+ }
+
+ // If not exists, add one.
+ if( !found )
+ {
+ String[] newAttrIds = new String[ attrIds.length + 1 ];
+ System.arraycopy( attrIds, 0, newAttrIds, 0, attrIds.length );
+ newAttrIds[ attrIds.length ] = Constants.ENTRY_DELETED;
+ attrIds = newAttrIds;
+ }
+
+ Attributes result = nextInterceptor.lookup( (LdapDN)name, attrIds );
+ ensureNotDeleted( name, result );
+ return result;
+ }
+
+
+ public NamingEnumeration list( NextInterceptor nextInterceptor, Name baseName ) throws NamingException
+ {
+ NamingEnumeration e = nextInterceptor.list( (LdapDN)baseName );
+ return new SearchResultFilteringEnumeration( e, new SearchControls(), InvocationStack.getInstance().peek(), Constants.DELETED_ENTRIES_FILTER );
+ }
+
+
+ public NamingEnumeration search( NextInterceptor nextInterceptor, Name baseName, Map environment, ExprNode filter, SearchControls searchControls ) throws NamingException
+ {
+ NamingEnumeration e = nextInterceptor.search( (LdapDN)baseName, environment, filter, searchControls );
+ if ( searchControls.getReturningAttributes() != null )
+ {
+ return e;
+ }
+
+ return new SearchResultFilteringEnumeration( e, searchControls, InvocationStack.getInstance().peek(), Constants.DELETED_ENTRIES_FILTER );
+ }
+
+ private void ensureNotDeleted( Name name, Attributes entry ) throws NamingException, LdapNameNotFoundException
+ {
+ if( isDeleted( entry ) )
+ {
+ LdapNameNotFoundException e =
+ new LdapNameNotFoundException( "Deleted entry: " + name );
+ e.setResolvedName( nexus.getMatchedName( (LdapDN)name ) );
+ throw e;
+ }
+ }
+
+ private boolean isDeleted( Attributes entry ) throws NamingException
+ {
+ if( entry == null )
+ {
+ return true;
+ }
+
+ Attribute deleted = entry.get( Constants.ENTRY_DELETED );
+ return ( deleted != null && "true".equals( deleted.get().toString() ) );
+ }
+}
Added: directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/ReplicationServiceException.java
URL: http://svn.apache.org/viewvc/directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/ReplicationServiceException.java?view=auto&rev=463366
==============================================================================
--- directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/ReplicationServiceException.java (added)
+++ directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/ReplicationServiceException.java Thu Oct 12 11:33:14 2006
@@ -0,0 +1,47 @@
+/*
+ * 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.mitosis.service;
+
+import org.apache.directory.mitosis.common.ReplicationException;
+
+public class ReplicationServiceException extends ReplicationException
+{
+ private static final long serialVersionUID = 3906090070204430386L;
+
+ public ReplicationServiceException()
+ {
+ super();
+ }
+
+ public ReplicationServiceException( String message, Throwable cause )
+ {
+ super( message, cause );
+ }
+
+ public ReplicationServiceException( String message )
+ {
+ super( message );
+ }
+
+ public ReplicationServiceException( Throwable cause )
+ {
+ super( cause );
+ }
+}
Added: directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/SimpleReplicationContext.java
URL: http://svn.apache.org/viewvc/directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/SimpleReplicationContext.java?view=auto&rev=463366
==============================================================================
--- directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/SimpleReplicationContext.java (added)
+++ directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/SimpleReplicationContext.java Thu Oct 12 11:33:14 2006
@@ -0,0 +1,178 @@
+/*
+ * 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.mitosis.service;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import org.apache.directory.server.core.DirectoryServiceConfiguration;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.util.SessionLog;
+import org.apache.directory.mitosis.common.Replica;
+import org.apache.directory.mitosis.configuration.ReplicationConfiguration;
+import org.apache.directory.mitosis.service.protocol.message.BaseMessage;
+
+public class SimpleReplicationContext implements ReplicationContext
+{
+ private static final Timer expirationTimer = new Timer( "ReplicationMessageExpirer" );
+
+ private final ReplicationService service;
+ private final ReplicationConfiguration configuration;
+ private final DirectoryServiceConfiguration serviceConfiguration;
+ private final IoSession session;
+ private final Map expirableMessages = new HashMap();
+ private int nextSequence;
+ private Replica peer;
+ private State state = State.INIT;
+
+ public SimpleReplicationContext( ReplicationService service, DirectoryServiceConfiguration serviceCfg, ReplicationConfiguration configuration, IoSession session )
+ {
+ this.service = service;
+ this.configuration = configuration;
+ this.serviceConfiguration = serviceCfg;
+ this.session = session;
+ }
+
+ public ReplicationService getService()
+ {
+ return service;
+ }
+
+ public ReplicationConfiguration getConfiguration()
+ {
+ return configuration;
+ }
+
+ public DirectoryServiceConfiguration getServiceConfiguration()
+ {
+ return serviceConfiguration;
+ }
+
+ public IoSession getSession()
+ {
+ return session;
+ }
+
+ public int getNextSequence()
+ {
+ return nextSequence ++;
+ }
+
+ public Replica getPeer()
+ {
+ return peer;
+ }
+
+ public void setPeer( Replica peer )
+ {
+ assert peer != null;
+ this.peer = peer;
+ }
+
+ public State getState()
+ {
+ return state;
+ }
+
+ public void setState( State state )
+ {
+ this.state = state;
+ }
+
+ public void scheduleExpiration( Object message )
+ {
+ BaseMessage bm = ( BaseMessage ) message;
+ ExpirationTask task = new ExpirationTask( bm );
+ synchronized( expirableMessages )
+ {
+ expirableMessages.put(
+ new Integer( bm.getSequence() ),
+ task );
+ }
+
+ expirationTimer.schedule( task, configuration.getResponseTimeout() * 1000L );
+ }
+
+ public Object cancelExpiration( int sequence )
+ {
+ ExpirationTask task = removeTask( sequence );
+ if( task == null )
+ {
+ return null;
+ }
+
+ task.cancel();
+ return task.message;
+ }
+
+ public void cancelAllExpirations()
+ {
+ synchronized( expirableMessages )
+ {
+ Iterator i = expirableMessages.values().iterator();
+ while( i.hasNext() )
+ {
+ ( ( ExpirationTask ) i.next() ).cancel();
+ }
+ }
+ }
+
+ public int getScheduledExpirations()
+ {
+ synchronized( expirableMessages )
+ {
+ return expirableMessages.size();
+ }
+ }
+
+ private ExpirationTask removeTask( int sequence )
+ {
+ ExpirationTask task;
+ synchronized( expirableMessages )
+ {
+ task = ( ExpirationTask ) expirableMessages.remove( new Integer( sequence ) );
+ }
+ return task;
+ }
+
+ private class ExpirationTask extends TimerTask
+ {
+ private final BaseMessage message;
+
+ private ExpirationTask( Object message )
+ {
+ this.message = ( BaseMessage ) message;
+ }
+
+ public void run()
+ {
+ if( removeTask( message.getSequence() ) == this )
+ {
+ SessionLog.warn(
+ getSession(),
+ "No response within " + configuration.getResponseTimeout() + " second(s) for message #" + message.getSequence() );
+ getSession().close();
+ }
+ }
+ }
+}
Added: directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/protocol/Constants.java
URL: http://svn.apache.org/viewvc/directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/protocol/Constants.java?view=auto&rev=463366
==============================================================================
--- directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/protocol/Constants.java (added)
+++ directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/protocol/Constants.java Thu Oct 12 11:33:14 2006
@@ -0,0 +1,41 @@
+/*
+ * 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.mitosis.service.protocol;
+
+public class Constants
+{
+ public static final int LOGIN = 0x00;
+ public static final int LOGIN_ACK = 0x01;
+ public static final int GET_UPDATE_VECTOR = 0x02;
+ public static final int GET_UPDATE_VECTOR_ACK = 0x03;
+ public static final int LOG_ENTRY = 0x04;
+ public static final int LOG_ENTRY_ACK = 0x05;
+ public static final int BEGIN_LOG_ENTRIES = 0x06;
+ public static final int BEGIN_LOG_ENTRIES_ACK = 0x07;
+ public static final int END_LOG_ENTRIES = 0x08;
+ public static final int END_LOG_ENTRIES_ACK = 0x09;
+
+ public static final int OK = 0;
+ public static final int NOT_OK = -1;
+
+ private Constants()
+ {
+ }
+}
Added: directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/protocol/codec/BaseMessageDecoder.java
URL: http://svn.apache.org/viewvc/directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/protocol/codec/BaseMessageDecoder.java?view=auto&rev=463366
==============================================================================
--- directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/protocol/codec/BaseMessageDecoder.java (added)
+++ directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/protocol/codec/BaseMessageDecoder.java Thu Oct 12 11:33:14 2006
@@ -0,0 +1,99 @@
+/*
+ * 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.mitosis.service.protocol.codec;
+
+import org.apache.directory.mitosis.service.protocol.message.BaseMessage;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.codec.ProtocolDecoderException;
+import org.apache.mina.filter.codec.ProtocolDecoderOutput;
+import org.apache.mina.filter.codec.demux.MessageDecoder;
+import org.apache.mina.filter.codec.demux.MessageDecoderResult;
+
+public abstract class BaseMessageDecoder implements MessageDecoder
+{
+ private final int type;
+ private final int minBodyLength;
+ private final int maxBodyLength;
+ private boolean readHeader;
+ private int sequence;
+ private int bodyLength;
+
+ protected BaseMessageDecoder( int type, int minBodyLength, int maxBodyLength )
+ {
+ this.type = type;
+ this.minBodyLength = minBodyLength;
+ this.maxBodyLength = maxBodyLength;
+ }
+
+ public final MessageDecoderResult decodable( IoSession session, ByteBuffer buf )
+ {
+ return type == buf.get()? OK : NOT_OK;
+ }
+
+ public final MessageDecoderResult decode( IoSession session, ByteBuffer in,
+ ProtocolDecoderOutput out ) throws Exception
+ {
+ if( !readHeader )
+ {
+ if( in.remaining() < 9 )
+ {
+ return NEED_DATA;
+ }
+
+ in.get(); // skip type field
+ sequence = in.getInt();
+ bodyLength = in.getInt();
+
+ if( bodyLength < minBodyLength || bodyLength > maxBodyLength )
+ {
+ throw new ProtocolDecoderException( "Wrong bodyLength: " + bodyLength );
+ }
+
+ readHeader = true;
+ }
+
+ if( readHeader )
+ {
+ if( in.remaining() < bodyLength )
+ {
+ return NEED_DATA;
+ }
+
+ int oldLimit = in.limit();
+
+ try
+ {
+ in.limit( in.position() + bodyLength );
+ out.write( decodeBody( sequence, bodyLength, in ) );
+ return OK;
+ }
+ finally
+ {
+ readHeader = false;
+ in.limit( oldLimit );
+ }
+ }
+
+ throw new InternalError();
+ }
+
+ protected abstract BaseMessage decodeBody( int sequence, int bodyLength, ByteBuffer in ) throws Exception;
+}
Added: directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/protocol/codec/BaseMessageEncoder.java
URL: http://svn.apache.org/viewvc/directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/protocol/codec/BaseMessageEncoder.java?view=auto&rev=463366
==============================================================================
--- directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/protocol/codec/BaseMessageEncoder.java (added)
+++ directory/trunks/apacheds/mitosis/src/main/java/org/apache/directory/mitosis/service/protocol/codec/BaseMessageEncoder.java Thu Oct 12 11:33:14 2006
@@ -0,0 +1,58 @@
+/*
+ * 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.mitosis.service.protocol.codec;
+
+import org.apache.directory.mitosis.service.protocol.message.BaseMessage;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.codec.ProtocolEncoderOutput;
+import org.apache.mina.filter.codec.demux.MessageEncoder;
+
+public abstract class BaseMessageEncoder implements MessageEncoder
+{
+ public BaseMessageEncoder()
+ {
+ }
+
+ public final void encode( IoSession session, Object in, ProtocolEncoderOutput out) throws Exception
+ {
+ BaseMessage m = ( BaseMessage ) in;
+ ByteBuffer buf = ByteBuffer.allocate( 16 );
+ buf.setAutoExpand( true );
+ buf.put( ( byte ) m.getType() );
+ buf.putInt( m.getSequence() );
+ buf.putInt( 0 ); // placeholder for body length field
+
+ final int bodyStartPos = buf.position();
+ encodeBody( m, buf );
+ final int bodyEndPos = buf.position();
+ final int bodyLength = bodyEndPos - bodyStartPos;
+
+ // fill bodyLength
+ buf.position( bodyStartPos - 4 );
+ buf.putInt( bodyLength );
+ buf.position( bodyEndPos );
+
+ buf.flip();
+ out.write( buf );
+ }
+
+ protected abstract void encodeBody( BaseMessage in, ByteBuffer out ) throws Exception;
+}