001: /**
002: * Redistribution and use of this software and associated documentation
003: * ("Software"), with or without modification, are permitted provided
004: * that the following conditions are met:
005: *
006: * 1. Redistributions of source code must retain copyright
007: * statements and notices. Redistributions must also contain a
008: * copy of this document.
009: *
010: * 2. Redistributions in binary form must reproduce the
011: * above copyright notice, this list of conditions and the
012: * following disclaimer in the documentation and/or other
013: * materials provided with the distribution.
014: *
015: * 3. The name "Exolab" must not be used to endorse or promote
016: * products derived from this Software without prior written
017: * permission of Intalio, Inc. For written permission,
018: * please contact info@exolab.org.
019: *
020: * 4. Products derived from this Software may not be called "Exolab"
021: * nor may "Exolab" appear in their names without prior written
022: * permission of Intalio, Inc. Exolab is a registered
023: * trademark of Intalio, Inc.
024: *
025: * 5. Due credit should be given to the Exolab Project
026: * (http://www.exolab.org/).
027: *
028: * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS
029: * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
030: * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
031: * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
032: * INTALIO, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
033: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
034: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
035: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
036: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
037: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
038: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
039: * OF THE POSSIBILITY OF SUCH DAMAGE.
040: *
041: * Copyright 1999 (C) Intalio, Inc. All Rights Reserved.
042: *
043: * $Id: ImportDescriptor.java 5951 2006-05-30 22:18:48Z bsnyder $
044: */package org.exolab.castor.dsml;
045:
046: import java.io.Serializable;
047: import java.util.Hashtable;
048: import java.util.Enumeration;
049: import java.util.StringTokenizer;
050: import org.xml.sax.DocumentHandler;
051: import org.xml.sax.AttributeList;
052: import org.xml.sax.SAXException;
053: import org.xml.sax.HandlerBase;
054: import org.xml.sax.helpers.AttributeListImpl;
055: import org.castor.util.Messages;
056:
057: /**
058: *
059: *
060: * @author <a href="mailto:arkin@intalio.com">Assaf Arkin</a>
061: * @version $Revision: 5951 $ $Date: 2006-04-25 15:08:23 -0600 (Tue, 25 Apr 2006) $
062: */
063: public class ImportDescriptor extends HandlerBase implements
064: Serializable {
065: /** SerialVersionUID */
066: private static final long serialVersionUID = 197365948293655041L;
067:
068: public static class Policy {
069: /**
070: * Under the <code>DeleteEmpty</code> policy, entries without attributes in the DSML are deleted from the Ldap.
071: */
072: public static final int DeleteEmpty = 0x01;
073: /**
074: * Under the <code>ReplaceAttr</code> policy, attributes in the Ldap that are not specified in the DSML are deleted.
075: */
076: public static final int ReplaceAttr = 0x02;
077: /**
078: * Under the <code>RefreshOnly</code> policy, DSML entries that do not already exist in the Ldap are not created.
079: */
080: public static final int RefreshOnly = 0x04;
081: /**
082: * Under the <code>NewAttrOnly</code> policy, new attributes are created according to the DSML,
083: but attributes that already have a value in the ldap are not updated.
084: */
085: public static final int NewAttrOnly = 0x08;
086: /**
087: * Under the <code>UpdateOnly</code> policy, DSML attributes that do not already exist in the Ldap are not created.
088: */
089: public static final int UpdateOnly = 0x10;
090: /**
091: * Under the <code>DefaultPolicy</code> policy,
092: */
093: public static final int DefaultPolicy = 0x00;
094: }
095:
096: static class Names {
097: static class Element {
098: public static final String Policies = "import-policies";
099: public static final String Policy = "import-policy";
100: }
101:
102: static class Attribute {
103: public static final String DN = "dn";
104: public static final String DeleteEmpty = "delete-empty";
105: public static final String ReplaceAttr = "replace-attr";
106: public static final String RefreshOnly = "refresh-only";
107: public static final String UpdateOnly = "update-only";
108: public static final String NewAttrOnly = "new-attr-only";
109: }
110: }
111:
112: private Hashtable _policies = new Hashtable();
113:
114: private boolean _insideRoot;
115:
116: public ImportDescriptor() {
117: }
118:
119: public Enumeration listDNs() {
120: return _policies.keys();
121: }
122:
123: public void addPolicy(String name, int policy) {
124: _policies.put(name, new Integer(policy));
125: }
126:
127: public int getDirectPolicy(String name) {
128: Integer policy;
129:
130: policy = (Integer) _policies.get(name);
131: if (policy != null)
132: return policy.intValue();
133:
134: return Policy.DefaultPolicy;
135: }
136:
137: public int getPolicy(String name) {
138: DN dn;
139: Integer policy;
140: int i;
141:
142: policy = (Integer) _policies.get(name);
143: if (policy != null)
144: return policy.intValue();
145: dn = new DN(name);
146: for (i = 1; i < dn.size(); ++i) {
147: name = dn.suffix(i);
148: policy = (Integer) _policies.get(name);
149: if (policy != null)
150: return policy.intValue();
151: }
152: return Policy.DefaultPolicy;
153: }
154:
155: public void produce(DocumentHandler docHandler) throws SAXException {
156: AttributeListImpl attrList;
157: int policy;
158: Enumeration enumeration;
159: String name;
160:
161: attrList = new AttributeListImpl();
162: docHandler.startElement(XML.Namespace.Root, attrList);
163: attrList = new AttributeListImpl();
164: docHandler.startElement(Names.Element.Policies, attrList);
165:
166: enumeration = listDNs();
167: while (enumeration.hasMoreElements()) {
168: name = (String) enumeration.nextElement();
169: policy = getDirectPolicy(name);
170: attrList = new AttributeListImpl();
171: attrList.addAttribute(Names.Attribute.DN, "ID", name);
172: if ((policy & Policy.DeleteEmpty) != 0)
173: attrList.addAttribute(Names.Attribute.DeleteEmpty,
174: null, "true");
175: if ((policy & Policy.ReplaceAttr) != 0)
176: attrList.addAttribute(Names.Attribute.ReplaceAttr,
177: null, "true");
178: if ((policy & Policy.RefreshOnly) != 0)
179: attrList.addAttribute(Names.Attribute.RefreshOnly,
180: null, "true");
181: if ((policy & Policy.UpdateOnly) != 0)
182: attrList.addAttribute(Names.Attribute.UpdateOnly, null,
183: "true");
184: if ((policy & Policy.NewAttrOnly) != 0)
185: attrList.addAttribute(Names.Attribute.NewAttrOnly,
186: null, "true");
187: docHandler.startElement(Names.Element.Policy, attrList);
188: docHandler.endElement(Names.Element.Policy);
189: }
190:
191: docHandler.endElement(Names.Element.Policies);
192: docHandler.endElement(XML.Namespace.Root);
193: }
194:
195: public void startElement(String tagName, AttributeList attr)
196: throws SAXException {
197: String dn;
198: int policy;
199:
200: if (tagName.equals(XML.Namespace.Root)) {
201: // Flag when entering (and leaving) the root element.
202: if (_insideRoot)
203: throw new SAXException(Messages.format(
204: "dsml.elementNested", XML.Namespace.Root));
205: _insideRoot = true;
206: } else {
207: if (!_insideRoot)
208: throw new SAXException(Messages.format(
209: "dsml.expectingOpeningTag", XML.Namespace.Root,
210: tagName));
211:
212: if (tagName.equals(Names.Element.Policies)) {
213: // Nothing to do at level of top element
214: } else if (tagName.equals(Names.Element.Policy)) {
215: dn = attr.getValue(Names.Attribute.DN);
216: if (dn == null)
217: throw new SAXException(Messages.format(
218: "dsml.missingAttribute",
219: Names.Element.Policy, Names.Attribute.DN));
220: policy = 0;
221: if ("true".equals(attr
222: .getValue(Names.Attribute.DeleteEmpty)))
223: policy = policy | Policy.DeleteEmpty;
224: if ("true".equals(attr
225: .getValue(Names.Attribute.RefreshOnly)))
226: policy = policy | Policy.RefreshOnly;
227: if ("true".equals(attr
228: .getValue(Names.Attribute.ReplaceAttr)))
229: policy = policy | Policy.ReplaceAttr;
230: if ("true".equals(attr
231: .getValue(Names.Attribute.NewAttrOnly)))
232: policy = policy | Policy.NewAttrOnly;
233: if ("true".equals(attr
234: .getValue(Names.Attribute.UpdateOnly)))
235: policy = policy | Policy.UpdateOnly;
236: addPolicy(dn, policy);
237: } else {
238: throw new SAXException(Messages.format(
239: "dsml.expectingOpeningTag",
240: Names.Element.Policies, tagName));
241: }
242: }
243: }
244:
245: public void endElement(String tagName) throws SAXException {
246: if (tagName.equals(XML.Namespace.Root)) {
247: if (_insideRoot)
248: _insideRoot = false;
249: else
250: throw new SAXException(Messages.format(
251: "dsml.closingOutsideRoot", tagName));
252: } else {
253: if (!_insideRoot)
254: throw new SAXException(Messages.format(
255: "dsml.closingOutsideRoot", tagName));
256: if (tagName.equals(Names.Element.Policies)) {
257: // Nothing to do here
258: } else if (tagName.equals(Names.Element.Policy)) {
259: // Nothing to do here
260: } else {
261: throw new SAXException(Messages.format(
262: "dsml.expectingClosingTag",
263: Names.Element.Policies, tagName));
264: }
265: }
266: }
267:
268: static class DN {
269:
270: private String[] _names;
271:
272: DN(String name) {
273: StringTokenizer token;
274: int i;
275:
276: token = new StringTokenizer(name, ", ");
277: _names = new String[token.countTokens()];
278: for (i = 0; token.hasMoreTokens(); ++i) {
279: _names[i] = token.nextToken();
280: }
281: }
282:
283: int size() {
284: return _names.length;
285: }
286:
287: String suffix(int index) {
288: StringBuffer name;
289:
290: name = new StringBuffer(_names[index]);
291: for (++index; index < _names.length; ++index) {
292: name.append(',').append(_names[index]);
293: }
294: return name.toString();
295: }
296:
297: }
298:
299: }
|