View Javadoc
1   /**
2    * Redistribution and use of this software and associated documentation ("Software"), with or
3    * without modification, are permitted provided that the following conditions are met:
4    *
5    * 1. Redistributions of source code must retain copyright statements and notices. Redistributions
6    * must also contain a copy of this document.
7    *
8    * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
9    * conditions and the following disclaimer in the documentation and/or other materials provided with
10   * the distribution.
11   *
12   * 3. The name "Exolab" must not be used to endorse or promote products derived from this Software
13   * without prior written permission of Intalio, Inc. For written permission, please contact
14   * info@exolab.org.
15   *
16   * 4. Products derived from this Software may not be called "Exolab" nor may "Exolab" appear in
17   * their names without prior written permission of Intalio, Inc. Exolab is a registered trademark of
18   * Intalio, Inc.
19   *
20   * 5. Due credit should be given to the Exolab Project (http://www.exolab.org/).
21   *
22   * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR
23   * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
24   * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTALIO, INC. OR ITS
25   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28   * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
29   * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30   *
31   * Copyright 1999 (C) Intalio, Inc. All Rights Reserved.
32   *
33   * $Id$
34   */
35  
36  
37  package org.exolab.castor.dsml;
38  
39  
40  import java.io.Serializable;
41  import java.util.Hashtable;
42  import java.util.Enumeration;
43  import java.util.StringTokenizer;
44  import org.xml.sax.DocumentHandler;
45  import org.xml.sax.AttributeList;
46  import org.xml.sax.SAXException;
47  import org.xml.sax.HandlerBase;
48  import org.xml.sax.helpers.AttributeListImpl;
49  import org.castor.core.util.Messages;
50  
51  
52  /**
53   *
54   *
55   * @author <a href="mailto:arkin@intalio.com">Assaf Arkin</a>
56   * @version $Revision$ $Date: 2006-04-25 15:08:23 -0600 (Tue, 25 Apr 2006) $
57   */
58  public class ImportDescriptor extends HandlerBase implements Serializable {
59    /** SerialVersionUID. */
60    private static final long serialVersionUID = 197365948293655041L;
61  
62    public static class Policy {
63      /**
64       * Under the <code>DeleteEmpty</code> policy, entries without attributes in the DSML are deleted
65       * from the Ldap.
66       */
67      public static final int DELETE_EMPTY = 0x01;
68      /**
69       * Under the <code>ReplaceAttr</code> policy, attributes in the Ldap that are not specified in
70       * the DSML are deleted.
71       */
72      public static final int REPLACE_ATTRIBUTE = 0x02;
73      /**
74       * Under the <code>RefreshOnly</code> policy, DSML entries that do not already exist in the Ldap
75       * are not created.
76       */
77      public static final int REFRESH_ONLY = 0x04;
78      /**
79       * Under the <code>NewAttrOnly</code> policy, new attributes are created according to the DSML,
80       * but attributes that already have a value in the ldap are not updated.
81       */
82      public static final int NEW_ATTRIBUTE_ONLY = 0x08;
83      /**
84       * Under the <code>UpdateOnly</code> policy, DSML attributes that do not already exist in the
85       * Ldap are not created.
86       */
87      public static final int UPDATE_ONLY = 0x10;
88      /** Under the <code>DefaultPolicy</code> policy. */
89      public static final int DEFAULT_POLICY = 0x00;
90    }
91  
92    static class Names {
93      static class Element {
94        public static final String POLICIES = "import-policies";
95        public static final String POLICY = "import-policy";
96      }
97  
98      static class Attribute {
99        public static final String DN = "dn";
100       public static final String DELETE_EMPTY = "delete-empty";
101       public static final String REPLACE_ATTRIBUTE = "replace-attr";
102       public static final String REFRESH_ONLY = "refresh-only";
103       public static final String UPDATE_ONLY = "update-only";
104       public static final String NEW_ATTRIBUTE_ONLY = "new-attr-only";
105     }
106   }
107 
108   private Hashtable _policies = new Hashtable();
109 
110   private boolean _insideRoot;
111 
112   public ImportDescriptor() {}
113 
114   public Enumeration listDNs() {
115     return _policies.keys();
116   }
117 
118   public void addPolicy(final String name, final int policy) {
119     _policies.put(name, Integer.valueOf(policy));
120   }
121 
122   public int getDirectPolicy(final String name) {
123     Integer policy = (Integer) _policies.get(name);
124     if (policy != null) {
125       return policy.intValue();
126     }
127     return Policy.DEFAULT_POLICY;
128   }
129 
130   public int getPolicy(String name) {
131     DN dn;
132     Integer policy;
133     int i;
134 
135     policy = (Integer) _policies.get(name);
136     if (policy != null) {
137       return policy.intValue();
138     }
139     dn = new DN(name);
140     for (i = 1; i < dn.size(); ++i) {
141       name = dn.suffix(i);
142       policy = (Integer) _policies.get(name);
143       if (policy != null) {
144         return policy.intValue();
145       }
146     }
147     return Policy.DEFAULT_POLICY;
148   }
149 
150   public void produce(final DocumentHandler docHandler) throws SAXException {
151     AttributeListImpl attrList;
152     int policy;
153     Enumeration enumeration;
154     String name;
155 
156     attrList = new AttributeListImpl();
157     docHandler.startElement(XML.Namespace.ROOT, attrList);
158     attrList = new AttributeListImpl();
159     docHandler.startElement(Names.Element.POLICIES, attrList);
160 
161     enumeration = listDNs();
162     while (enumeration.hasMoreElements()) {
163       name = (String) enumeration.nextElement();
164       policy = getDirectPolicy(name);
165       attrList = new AttributeListImpl();
166       attrList.addAttribute(Names.Attribute.DN, "ID", name);
167       if ((policy & Policy.DELETE_EMPTY) != 0) {
168         attrList.addAttribute(Names.Attribute.DELETE_EMPTY, null, "true");
169       }
170       if ((policy & Policy.REPLACE_ATTRIBUTE) != 0) {
171         attrList.addAttribute(Names.Attribute.REPLACE_ATTRIBUTE, null, "true");
172       }
173       if ((policy & Policy.REFRESH_ONLY) != 0) {
174         attrList.addAttribute(Names.Attribute.REFRESH_ONLY, null, "true");
175       }
176       if ((policy & Policy.UPDATE_ONLY) != 0) {
177         attrList.addAttribute(Names.Attribute.UPDATE_ONLY, null, "true");
178       }
179       if ((policy & Policy.NEW_ATTRIBUTE_ONLY) != 0) {
180         attrList.addAttribute(Names.Attribute.NEW_ATTRIBUTE_ONLY, null, "true");
181       }
182       docHandler.startElement(Names.Element.POLICY, attrList);
183       docHandler.endElement(Names.Element.POLICY);
184     }
185 
186     docHandler.endElement(Names.Element.POLICIES);
187     docHandler.endElement(XML.Namespace.ROOT);
188   }
189 
190 
191   public void startElement(final String tagName, final AttributeList attr) throws SAXException {
192     String dn;
193     int policy;
194 
195     if (tagName.equals(XML.Namespace.ROOT)) {
196       // Flag when entering (and leaving) the root element.
197       if (_insideRoot) {
198         throw new SAXException(Messages.format("dsml.elementNested", XML.Namespace.ROOT));
199       }
200       _insideRoot = true;
201     } else {
202       if (!_insideRoot) {
203         throw new SAXException(
204             Messages.format("dsml.expectingOpeningTag", XML.Namespace.ROOT, tagName));
205       }
206 
207       if (tagName.equals(Names.Element.POLICIES)) {
208         // Nothing to do at level of top element
209       } else if (tagName.equals(Names.Element.POLICY)) {
210         dn = attr.getValue(Names.Attribute.DN);
211         if (dn == null) {
212           throw new SAXException(
213               Messages.format("dsml.missingAttribute", Names.Element.POLICY, Names.Attribute.DN));
214         }
215         policy = 0;
216         if (Boolean.parseBoolean(attr.getValue(Names.Attribute.DELETE_EMPTY))) {
217           policy = policy | Policy.DELETE_EMPTY;
218         }
219         if (Boolean.parseBoolean(attr.getValue(Names.Attribute.REFRESH_ONLY))) {
220           policy = policy | Policy.REFRESH_ONLY;
221         }
222         if (Boolean.parseBoolean(attr.getValue(Names.Attribute.REPLACE_ATTRIBUTE))) {
223           policy = policy | Policy.REPLACE_ATTRIBUTE;
224         }
225         if (Boolean.parseBoolean(attr.getValue(Names.Attribute.NEW_ATTRIBUTE_ONLY))) {
226           policy = policy | Policy.NEW_ATTRIBUTE_ONLY;
227         }
228         if (Boolean.parseBoolean(attr.getValue(Names.Attribute.UPDATE_ONLY))) {
229           policy = policy | Policy.UPDATE_ONLY;
230         }
231         addPolicy(dn, policy);
232       } else {
233         throw new SAXException(
234             Messages.format("dsml.expectingOpeningTag", Names.Element.POLICIES, tagName));
235       }
236     }
237   }
238 
239   public void endElement(final String tagName) throws SAXException {
240     if (tagName.equals(XML.Namespace.ROOT)) {
241       if (_insideRoot) {
242         _insideRoot = false;
243       } else {
244         throw new SAXException(Messages.format("dsml.closingOutsideRoot", tagName));
245       }
246     } else {
247       if (!_insideRoot) {
248         throw new SAXException(Messages.format("dsml.closingOutsideRoot", tagName));
249       }
250       if (tagName.equals(Names.Element.POLICIES)) {
251         // Nothing to do here
252       } else if (tagName.equals(Names.Element.POLICY)) {
253         // Nothing to do here
254       } else {
255         throw new SAXException(
256             Messages.format("dsml.expectingClosingTag", Names.Element.POLICIES, tagName));
257       }
258     }
259   }
260 
261   static class DN {
262     private String[] _names;
263 
264     DN(final String name) {
265       StringTokenizer token;
266       int i;
267 
268       token = new StringTokenizer(name, ", ");
269       _names = new String[token.countTokens()];
270       for (i = 0; token.hasMoreTokens(); ++i) {
271         _names[i] = token.nextToken();
272       }
273     }
274 
275     int size() {
276       return _names.length;
277     }
278 
279     String suffix(int index) {
280       StringBuilder name = new StringBuilder(_names[index]);
281       for (++index; index < _names.length; ++index) {
282         name.append(',').append(_names[index]);
283       }
284       return name.toString();
285     }
286   }
287 }