KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > de > webman > sync > SyncMgr


1 /**
2  * Webman - Content Management System
3  * Copyright (C) 1999-2002 Team-Konzept, Alexander Grosse, Charite
4
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  */

19 package de.webman.sync JavaDoc;
20
21 import de.webman.util.registry.Manager;
22 import de.webman.util.registry.RegistryException;
23 import org.apache.log4j.*;
24 import java.io.File JavaDoc;
25 import java.io.IOException JavaDoc;
26 import java.io.BufferedInputStream JavaDoc;
27 import java.io.FileInputStream JavaDoc;
28 import java.util.List JavaDoc;
29 import java.util.Iterator JavaDoc;
30 import org.w3c.dom.Node JavaDoc;
31 import org.w3c.dom.Document JavaDoc;
32 import org.xml.sax.SAXException JavaDoc;
33 import org.xml.sax.InputSource JavaDoc;
34 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
35 import javax.xml.parsers.DocumentBuilder JavaDoc;
36 import javax.xml.parsers.ParserConfigurationException JavaDoc;
37 import com.teamkonzept.webman.db.TKWebmanDBManager;
38 import java.sql.SQLException JavaDoc;
39 import com.teamkonzept.lib.TKException;
40 import com.teamkonzept.webman.db.TKWebmanDBManager;
41 import com.teamkonzept.db.TKPrepQuery;
42
43
44 /**
45  * A registry which initializes and setups the synchronization facility.
46  * It should be registered and loaded on start, when it is configured to
47  * use the timer facility.<p>
48  *
49  * At the same time this class implements the central synchronization
50  * management class, which implements the synchronization kernel
51  * functionality from webman vs. external access control system. The real
52  * work ("delete removed users from webman", "store webmangroups to access
53  * control system", etc.) is done by so called worker classes (implementing
54  * the {@link de.webman.sync.Worker} protocol).<p>
55  *
56  * Synchronization in webman is actually a multipass synchronization,
57  * depending on the actual backend implementation for the sync. The list
58  * of workers, doing the synchronization is requested by the {@link
59  * de.webman.sync.ACLAdaptor#getWorkers()} method. See in the actually {@link
60  * de.webman.sync.ACLAdaptor} (e.g. {@link de.webman.sync.ldap.LDAPAdaptor})
61  * implementations for detail.
62  *
63  * @author <a HREF="mailto:gregor@webman.de">Gregor Klinke</a>
64  * @version $Revision: 1.2.2.1 $
65  **/

66 public class SyncMgr
67     implements Manager
68 {
69     /* $Id $ */
70     /**
71      * logging facility
72      **/

73     private static Category cat = Category.getInstance(SyncMgr.class);
74     
75
76     /**
77      * the access control adaptor to use
78      **/

79     private ACLAdaptor adaptor = null;
80
81     /**
82      * the factory to load the acl adaptor
83      **/

84     private ACLAdaptorFactory adaptorfactory = null;
85     
86     /**
87      * the list of workers
88      **/

89     private List JavaDoc workers = null;
90
91     /**
92      * use external synchronization?
93      **/

94     private boolean doSync = false;
95
96     /**
97      * synchronize with the access control system?
98      **/

99     private boolean syncOnStart = false;
100
101     /**
102      * flag indicating, if busy synchronizating
103      **/

104     private boolean inCycle = false;
105
106
107     /**
108      * the constructor, only to be used by the related factory
109      * @param basedir the directory to read the configuration from
110      * @throws RegistryException cheese and butter
111      **/

112     SyncMgr(String JavaDoc basedir)
113         throws RegistryException
114     {
115         try {
116             cat.info("setup synchronization system");
117         
118             try {
119                 File JavaDoc syncfile = new File JavaDoc(basedir, "WEB-INF/classes/sync.xml");
120                 readXMLStream(new BufferedInputStream JavaDoc(new FileInputStream JavaDoc(syncfile)));
121             }
122             catch (IOException JavaDoc ioe) {
123                 cat.info ("no 'sync.xml' found");
124                 doSync = false;
125             }
126         
127             
128             if (doSync) {
129                 try {
130                     adaptorfactory.setProperty("basedir", basedir);
131                     adaptor = adaptorfactory.newACLAdaptor();
132                     workers = (List JavaDoc)adaptor.getWorkers();
133                     
134                     if (syncOnStart)
135                         sync();
136                     
137                     cat.info("synchronization system successfully started");
138                 }
139                 catch (Exception JavaDoc ioe) {
140                     throw new RegistryException(ioe);
141                 }
142             }
143             else
144                 cat.info("synchronization system disabled");
145         }
146         catch (Exception JavaDoc e) {
147             e.printStackTrace(System.out);
148         }
149
150     }
151   
152
153     /**
154      * runs a synchronization against the access control system
155      *
156      * @throws SyncException if anything failed during synchronization
157      **/

158     private void sync ()
159         throws SyncException
160     {
161         cat.debug("synchronize with ext. acl system");
162
163         try
164         {
165             try {
166                 TKWebmanDBManager.initConnection("/webmandb.ini", false);
167                 TKPrepQuery.enableCleanup();
168             }
169             catch (TKException e) {
170                 throw new SyncException(e);
171             }
172
173             if (workers != null) {
174                 for (Iterator JavaDoc it = workers.iterator(); it.hasNext(); ) {
175                     Worker worker = (Worker)it.next();
176
177                     worker.run(adaptor);
178                 }
179             }
180         }
181         finally
182         {
183             /* TODO: deregister the current thread! This is not done
184                automatically by the webman backend code ..., really, we do need
185                a better solution herefore! */

186             try {
187                 TKWebmanDBManager.deregister(true);
188             }
189             catch (SQLException JavaDoc e) {
190                 throw new SyncException(e);
191             }
192         }
193     }
194
195
196     /**
197      * runs a new synchronization cycle. Since synchronizations could not
198      * run concurrently in a proper way, any attempt to start a next
199      * synchronization with then external system throws an {@link
200      * de.webman.sync.SyncBusyException}.
201      *
202      * @throws SyncException if anything fails during synchronization
203      * @throws SyncBusyException if a synchronization is running in the moment; try again later
204      **/

205     public void runSynchronization()
206         throws SyncException, SyncBusyException
207     {
208         synchronized(this) {
209             if (inCycle)
210                 throw new SyncBusyException();
211             
212             inCycle = true;
213         }
214         
215         try {
216             sync();
217         }
218         finally {
219             synchronized(this) {
220                 inCycle = false;
221             }
222         }
223     }
224     
225
226     /* ----------------------------------------------------------------------
227        read configuration
228        ---------------------------------------------------------------------- */

229     /**
230      * reads a xml config file. for the xml structure see above
231      * @param in the config file as input stream
232      **/

233     private void readXMLStream(BufferedInputStream JavaDoc in)
234         throws IOException JavaDoc, RegistryException
235     {
236         DocumentBuilderFactory JavaDoc factory = DocumentBuilderFactory.newInstance();
237         factory.setNamespaceAware(false);
238         factory.setValidating(false);
239             
240         Document JavaDoc doc = null;
241         try {
242             DocumentBuilder JavaDoc builder = factory.newDocumentBuilder();
243             doc = builder.parse(new InputSource JavaDoc(in));
244         }
245         catch (ParserConfigurationException JavaDoc pce) {
246             throw new RegistryException(pce);
247         }
248         catch (SAXException JavaDoc se) {
249             throw new RegistryException(se);
250         }
251         
252         Node JavaDoc nd = doc.getDocumentElement();
253         if (!("synchronization".equals(nd.getNodeName())))
254             throw new RegistryException("bad root element '" + nd.getNodeName() + "'");
255         
256         for (Node JavaDoc c1 = nd.getFirstChild(); c1 != null; c1 = c1.getNextSibling()) {
257             if (c1.getNodeType() == Node.ELEMENT_NODE) {
258                 if ("use-sync".equals(c1.getNodeName())) {
259                     String JavaDoc val = getTextData(c1);
260                     doSync = (val != null && "TRUE".equals(val.trim().toUpperCase()));
261                 }
262                 else if ("sync-factory".equals(c1.getNodeName())) {
263                     if (doSync) {
264                         try {
265                             String JavaDoc factName = getTextData(c1);
266                             if (factName != null) {
267                                 Class JavaDoc fact = Class.forName(factName.trim());
268                                 
269                                 adaptorfactory = (ACLAdaptorFactory)fact.newInstance();
270                             }
271                             else {
272                                 adaptorfactory = null;
273                                 doSync = false;
274                             }
275                         }
276                         catch (Exception JavaDoc e) {
277                             cat.error("Can't setup ACL factory: " + e);
278                             doSync = false;
279                             throw new RegistryException(e);
280                         }
281                     }
282                 }
283                 else if ("sync-on-start".equals(c1.getNodeName())) {
284                     if (doSync) {
285                         String JavaDoc val = getTextData(c1);
286                         syncOnStart = (val != null && "TRUE".equals(val.trim().toUpperCase()));
287                     }
288                 }
289                 else
290                     throw new RegistryException("unknown element: '" + c1.getNodeName() + "'");
291             }
292         }
293
294         if (doSync && adaptorfactory == null)
295             throw new RegistryException("can't synchronize, missing sync-factory element");
296     }
297
298     /**
299      * returns the first text element below a context node
300      **/

301     private String JavaDoc getTextData(Node JavaDoc cntx) {
302         cntx.normalize();
303
304         for (Node JavaDoc n = cntx.getFirstChild(); n != null; n = n.getNextSibling()) {
305             if (n.getNodeType() == Node.TEXT_NODE) {
306                 return n.getNodeValue();
307             }
308             else if (n.getNodeType() == Node.CDATA_SECTION_NODE) {
309                 return n.getNodeValue();
310             }
311         }
312         return null;
313     }
314
315 }
316
Popular Tags