View Javadoc

1   /*
2    *   Copyright 2004 The Apache Software Foundation
3    *
4    *   Licensed under the Apache License, Version 2.0 (the "License");
5    *   you may not use this file except in compliance with the License.
6    *   You may obtain a copy of the License at
7    *
8    *       http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *   Unless required by applicable law or agreed to in writing, software
11   *   distributed under the License is distributed on an "AS IS" BASIS,
12   *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *   See the License for the specific language governing permissions and
14   *   limitations under the License.
15   *
16   */
17  package org.apache.ldap.server.jndi;
18  
19  
20  import org.apache.ldap.common.message.LockableAttributeImpl;
21  
22  import java.io.ByteArrayInputStream;
23  import java.io.ByteArrayOutputStream;
24  import java.io.IOException;
25  import java.io.ObjectInputStream;
26  import java.io.ObjectOutputStream;
27  
28  import javax.naming.NamingException;
29  import javax.naming.directory.Attributes;
30  import javax.naming.directory.Attribute;
31  
32  
33  /***
34   * Contains constants and serialization methods used to implement functionality
35   * associated with RFC 2713 which enables the storage and representation of Java
36   * objects within an LDAP directory.
37   *
38   * @see <a href="http://www.faqs.org/rfcs/rfc2713.html">RFC 2713</a>
39   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
40   * @version $Rev: 264732 $
41   */
42  class JavaLdapSupport
43  {
44      // ------------------------------------------------------------------------
45      // Attribute Id Constants Used By The Java LDAP BootstrapSchema
46      // ------------------------------------------------------------------------
47  
48      /*** objectClass attribute for top */
49      public static final String TOP_ATTR = "top";
50      /*** the javaObject attribute */
51      public static final String JOBJECT_ATTR = "javaObject";
52      /*** the objectClass attribute */
53      public static final String OBJECTCLASS_ATTR = "objectClass";
54      /*** the javaContainer attribute */
55      public static final String JCONTAINER_ATTR = "javaContainer";
56      /*** the javaSerializedObject attribute */
57      public static final String JSERIALIZEDOBJ_ATTR = "javaSerializedObject";
58  
59      /*** the javaClassName attribute */
60      public static final String JCLASSNAME_ATTR = "javaClassName";
61      /*** the javaClassNames attribute */
62      public static final String JCLASSNAMES_ATTR = "javaClassNames";
63      /*** the javaSerializedData attribute */
64      public static final String JSERIALDATA_ATTR = "javaSerializedData";
65  
66  
67      // ------------------------------------------------------------------------
68      // Package Friendly & Private Utility Methods 
69      // ------------------------------------------------------------------------
70  
71  
72      /***
73       * Resusitates an object from a serialized attribute in an entry that 
74       * conforms to the specifications for representing Java Objects in an LDAP 
75       * Directory (RFC 2713).
76       *
77       * @param attributes the entry representing a serialized object
78       * @return the deserialized object
79       * @throws NamingException if the object cannot be serialized
80       */
81      static Object deserialize( Attributes attributes ) throws NamingException
82      {
83          ObjectInputStream in = null;
84          String className = ( String ) attributes.get( JCLASSNAME_ATTR ).get();
85  
86          try
87          {
88              byte [] data = ( byte [] ) attributes.get( JSERIALDATA_ATTR ).get();
89              in = new ObjectInputStream( new ByteArrayInputStream( data ) );
90              return in.readObject();
91          }
92          catch ( Exception e )
93          {
94              NamingException ne = new NamingException( "De-serialization of '"
95                  + className + "' instance failed:\n" + e.getMessage() );
96              ne.setRootCause( e );
97              throw ne;
98          }
99          finally
100         {
101             try
102             {
103                 in.close();
104             }
105             catch ( IOException e )
106             {
107                 throw new NamingException( "object deserialization stream close() failure" );
108             }
109         }
110     }
111 
112     
113     /***
114      * Serializes an object into a byte array.
115      *
116      * @param obj the object to serialize
117      * @return the object's serialized byte array form
118      * @throws NamingException of the object cannot be serialized
119      */
120     static byte [] serialize( Object obj ) throws NamingException
121     {
122         ByteArrayOutputStream bytesOut = null;
123         ObjectOutputStream out = null;
124 
125         try
126         {
127             bytesOut = new ByteArrayOutputStream();
128             out = new ObjectOutputStream( bytesOut );
129             out.writeObject( obj );
130             return bytesOut.toByteArray();
131         }
132         catch ( Exception e )
133         {
134             NamingException ne = new NamingException( "Serialization of '"
135                 + obj + "' failed:\n" + e.getMessage() );
136             ne.setRootCause( e );
137             throw ne;
138         }
139         finally
140         {
141             try
142             {
143                 out.close();
144             }
145             catch ( IOException e )
146             {
147                 throw new NamingException( "object serialization stream close() failure" );
148             }
149         }
150     }
151 
152 
153     /***
154      * Serializes an object into an entry using the attributes specified in
155      * RFC 2713 to represent the serialized object.
156      *
157      * @param entry the set of attributes representing entry
158      * @param obj the object to serialize
159      * @throws NamingException if the object cannot be serialized
160      */
161     static void serialize( Attributes entry, Object obj ) throws NamingException
162     {
163         /* Let's add the object classes first:
164          * objectClass: top
165          * objectClass: javaObject
166          * objectClass: javaContainer
167          * objectClass: javaSerializedObject
168          */
169         Attribute objectClass = new LockableAttributeImpl( "objectClass" );
170         objectClass.add( TOP_ATTR );
171         objectClass.add( JOBJECT_ATTR );
172         objectClass.add( JCONTAINER_ATTR );
173         objectClass.add( JSERIALIZEDOBJ_ATTR );
174         entry.put( objectClass );
175 
176         // Add the javaClassName and javaSerializedData attributes
177         entry.put( JCLASSNAME_ATTR, obj.getClass().getName() );
178         entry.put( JSERIALDATA_ATTR, serialize( obj ) );
179 
180         // Add all the class names this object can be cast to:
181         Class [] classes = obj.getClass().getClasses();
182         Attribute javaClassNames = new LockableAttributeImpl( JCLASSNAMES_ATTR );
183 
184         for ( int ii = 0; ii < classes.length; ii++ )
185         {
186             javaClassNames.add( classes[ii].getName() );
187         }
188 
189         entry.put( javaClassNames );
190     }
191 }