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