1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 package org.openoffice.xmerge.util.registry;
25 
26 import java.util.*;
27 import java.io.*;
28 
29 /**
30  *  Manages the converter plug-ins that are currently active.
31  *  This class allows plug-ins to be added or removed dynamically.
32  *  This class is a singleton (static) class, so that only one
33  *  manager can exist at a time.  It is final, so it may not be
34  *  subclassed.
35  *
36  *  @author: Brian Cameron
37  */
38 public final class ConverterInfoMgr {
39 
40     private static Vector converterInfoList;
41 
42    /**
43     *  Constructor
44     */
45     static {
46        converterInfoList = new Vector();
47     }
48 
49 
50    /**
51     *  Adds a converter plug-in to the registry.  The
52     *  <code>ConverterInfo</code> must have a unique DisplayName
53     *  and must have non-null values for DisplayName, ClassImpl,
54     *  OfficeMime, and DeviceMime.
55     *
56     *  @param   ci  A <code>ConverterInfo</code> object
57     *                         describing a plug-in.
58     *
59     *  @throws  RegistryException  If the <code>ConverterInfo</code>
60     *                              is not valid.
61     */
addPlugIn(ConverterInfo ci)62     public static void addPlugIn(ConverterInfo ci) throws RegistryException {
63 
64         ConverterInfo converterInfo;
65 
66         // Validate
67         //
68         if (ci.getDisplayName() == null) {
69             RegistryException re = new RegistryException(
70                 "Converter must have valid name.");
71             throw re;
72         }
73         if (ci.getClassImpl() == null) {
74             RegistryException re = new RegistryException(
75                 "Converter must have valid class implementation specified.");
76             throw re;
77         }
78         if (ci.getOfficeMime() == null) {
79             RegistryException re = new RegistryException(
80                 "Converter must have valid office mime specified.");
81             throw re;
82         }
83         if (! ci.getDeviceMime().hasMoreElements()) {
84             RegistryException re = new RegistryException(
85                 "Converter must have valid device mime specified.");
86             throw re;
87         }
88 
89         // Verify there is no converter with the same Display Name in
90         // the registry.
91         //
92         Enumeration ciEnum = converterInfoList.elements();
93         while (ciEnum.hasMoreElements()) {
94             converterInfo = (ConverterInfo)ciEnum.nextElement();
95             if (ci.getDisplayName().equals(converterInfo.getDisplayName())) {
96                 RegistryException re = new RegistryException(
97                     "Converter with specified display name already exists.");
98                 throw re;
99             }
100         }
101 
102         // Since this is a adding to a static Vector, make sure this
103         // add method call is synchronized.
104         //
105         synchronized (converterInfoList) {
106             converterInfoList.add(ci);
107         }
108     }
109 
110 
111    /**
112     *  Adds an <code>Enumeration</code> of converter plug-ins to the registry.
113     *  Each <code>ConverterInfo</code> in the <code>Enumeration</code> must have
114     *  a unique DisplayName and must have non-null values for DisplayName,
115     *  ClassImpl, OfficeMime, and DeviceMime.
116     *
117     *  @param  jarEnum  An <code>Enumeration</code> of <code>ConverterInfo</code>
118     *                     objects describing one or more plug-in(s).
119     *
120     *  @throws  RegistryException  If a <code>ConverterInfo</code> in the
121     *                              <code>Enumeration</code> is not valid.
122     */
addPlugIn(Enumeration jarEnum)123     public static void addPlugIn(Enumeration jarEnum) throws RegistryException {
124 
125         while (jarEnum.hasMoreElements()) {
126             ConverterInfo converterInfo = (ConverterInfo)jarEnum.nextElement();
127             addPlugIn(converterInfo);
128         }
129     }
130 
131 
132    /**
133     *  Returns an <code>Enumeration</code> of registered
134     *  <code>ConverterInfo</code> objects.
135     *
136     *  @return  An <code>Enumeration</code> containing the currently registered
137     *           <code>ConverterInfo</code> objects, an empty
138     *           <code>Vector</code> if none exist.
139     */
getConverterInfoEnumeration()140    public static Enumeration getConverterInfoEnumeration() {
141       return (converterInfoList.elements());
142    }
143 
144 
145    /**
146     *  Removes any <code>ConverterInfo</code> object from the registry
147     *  that have the specified jar name value.
148     *
149     *  @param  jar  The name of the jarfile.
150     *
151     *  @return  True if a <code>ConverterInfo</code> object was
152     *           removed, false otherwise.
153     */
removeByJar(String jar)154    public static boolean removeByJar(String jar) {
155 
156         ConverterInfo converterInfo;
157         boolean       rc = false;
158 
159         // FIX (HJ): Has to use an iterator, since we are removing items
160         /*Enumeration ciEnum = converterInfoList.elements();
161         while (ciEnum.hasMoreElements())
162         {
163             converterInfo = (ConverterInfo)ciEnum.nextElement();
164             if (jar.equals(converterInfo.getJarName())) {
165                converterInfoList.remove(converterInfo);
166                rc = true;
167             }
168         }*/
169 
170         Iterator ciIter = converterInfoList.iterator();
171         while (ciIter.hasNext())
172         {
173             converterInfo = (ConverterInfo)ciIter.next();
174             if (jar.equals(converterInfo.getJarName())) {
175                ciIter.remove();
176                rc = true;
177             }
178         }
179         return rc;
180     }
181 
182 
183    /**
184     *  Removes any <code>ConverterInfo</code> object from the registry
185     *  that have the specified display name value.
186     *
187     *  @param  name  The display name.
188     *
189     *  @return  True if a <code>ConverterInfo</code> object was
190     *           removed, false otherwise.
191     */
removeByName(String name)192    public static boolean removeByName(String name) {
193 
194         ConverterInfo converterInfo;
195         boolean       rc = false;
196 
197         Enumeration ciEnum = converterInfoList.elements();
198         while (ciEnum.hasMoreElements())
199         {
200             converterInfo = (ConverterInfo)ciEnum.nextElement();
201             if (name.equals(converterInfo.getDisplayName())) {
202                converterInfoList.remove(converterInfo);
203                rc = true;
204             }
205         }
206         return rc;
207     }
208 
209 
210    /**
211     *  Returns the <code>ConverterInfo</code> object that supports
212     *  the specified device/office mime type conversion.  If there
213     *  are multiple <code>ConverterInfo</code> objects registered
214     *  that support this conversion, only the first is returned.
215     *
216     *  @param  deviceMime  The device mime.
217     *  @param  officeMime  The office mime.
218     *
219     *  @return  The first plug-in that supports the specified
220     *           conversion.
221     */
findConverterInfo(String deviceMime, String officeMime)222     public static ConverterInfo findConverterInfo(String deviceMime, String officeMime) {
223 
224         ConverterInfo converterInfo;
225 
226         if (deviceMime == null ||
227             ConverterInfo.isValidOfficeType(officeMime) == false) {
228             return null;
229         }
230 
231         // Loop over elements comparing with deviceFromMime
232         //
233         Enumeration ciEnum = converterInfoList.elements();
234         while (ciEnum.hasMoreElements()) {
235 
236             converterInfo = (ConverterInfo)ciEnum.nextElement();
237             String toDeviceInfo = (String)converterInfo.getOfficeMime();
238             Enumeration fromEnum = converterInfo.getDeviceMime();
239 
240             // Loop over the deviceMime types.
241             //
242             while (fromEnum.hasMoreElements()) {
243                 String fromDeviceInfo = (String)fromEnum.nextElement();
244                 if (deviceMime.trim().equals(fromDeviceInfo) &&
245                     officeMime.trim().equals(toDeviceInfo)) {
246                    return (converterInfo);
247                 }
248             }
249         }
250         return null;
251     }
252 
253 
254    /**
255     *  Returns an array of two <code>ConverterInfo</code> objects that
256     *  can be chained to perform the specified mime type conversion.
257     *  If there are multiple <code>ConverterInfo</code> objects that
258     *  support this conversion, only the first is returned.
259     *
260     *  @param  deviceFromMime  The device from mime.
261     *  @param  deviceToMime    The device to mime.
262     *
263     *  @return  An array of two <code>ConverterInfo</code> objects
264     *           that can be chained to perform the specified
265     *           conversion.
266     */
findConverterInfoChain(String deviceFromMime, String deviceToMime)267     public static ConverterInfo[] findConverterInfoChain(String deviceFromMime, String deviceToMime) {
268 
269         if (deviceFromMime == null || deviceToMime == null) {
270             return null;
271         }
272 
273         ConverterInfo[] converterInfo = new ConverterInfo[2];
274 
275         // Loop over elements comparing with deviceFromMime
276         //
277         Enumeration cifEnum = converterInfoList.elements();
278         while (cifEnum.hasMoreElements()) {
279 
280             converterInfo[0] = (ConverterInfo)cifEnum.nextElement();
281             String fromOfficeInfo = converterInfo[0].getOfficeMime();
282             Enumeration fromEnum = converterInfo[0].getDeviceMime();
283 
284             // Loop over the deviceMime types looking for a deviceFromMime
285             // match.
286             //
287             while (fromEnum.hasMoreElements()) {
288                 String fromDeviceInfo = (String)fromEnum.nextElement();
289 
290                 if (deviceFromMime.trim().equals(fromDeviceInfo)) {
291 
292                     // Found a a match for deviceFrom.  Now loop over the
293                     // elements comparing with deviceToMime
294                     //
295                     Enumeration citEnum = converterInfoList.elements();
296                     while (citEnum.hasMoreElements()) {
297 
298                         converterInfo[1] = (ConverterInfo)citEnum.nextElement();
299                         String toOfficeInfo = converterInfo[1].getOfficeMime();
300                         Enumeration toEnum = converterInfo[1].getDeviceMime();
301 
302                         // Loop over deviceMime types looking for a
303                         // deviceToMime match.
304                         //
305                         while (toEnum.hasMoreElements()) {
306                             String toDeviceInfo = (String)toEnum.nextElement();
307                             if (deviceToMime.trim().equals(toDeviceInfo) &&
308                                 fromOfficeInfo.equals(toOfficeInfo)) {
309 
310                                 // Found a match
311                                 //
312                                 return (converterInfo);
313                             }
314                         }
315                     }
316                 }
317             }
318         }
319         return null;
320     }
321 
322 
323     /**
324      *  main to let the user specify what plug-ins to register from
325      *  jarfiles and to display the currently registered plug-ins.
326      *
327      *  @param  args  Not used.
328      */
main(String args[])329     public static void main(String args[]) {
330 
331         ConverterInfoReader cir = null;
332 	boolean validate = false;
333         InputStreamReader   isr = new InputStreamReader(System.in);
334         BufferedReader      br  = new BufferedReader(isr);
335         char                c   = ' ';
336 
337         boolean exitFlag = false;
338         while (exitFlag == false) {
339 
340             System.out.println("\nMenu:");
341             System.out.println("(L)oad plug-ins from a jar file");
342             System.out.println("(D)isplay name unload");
343             System.out.println("(J)ar name unload");
344             System.out.println("(F)ind ConverterInfo");
345             System.out.println("(C)ind ConverterInfo chain");
346             System.out.println("(V)iew plug-ins");
347 	    System.out.println("(T)oggle Validation");
348             System.out.println("(Q)uit\n");
349 
350             try {
351                 c = br.readLine().toUpperCase().trim().charAt(0);
352             } catch(Exception e) {
353                 System.out.println("Invalid entry");
354                 System.out.println("Error msg: " + e.getMessage());
355                 continue;
356             }
357 
358             System.out.println("");
359 
360             // Quit
361             //
362             if (c == 'Q') {
363                 exitFlag = true;
364 
365             // Load by Jarfile
366             //
367             } else if (c == 'L') {
368 
369                 System.out.println("Enter path to jarfile: ");
370                 try {
371                     String jarname = br.readLine().trim();
372                     cir = new ConverterInfoReader(jarname,validate);
373                 } catch (RegistryException e) {
374                     System.out.println("Cannot load plug-in ConverterFactory implementation.");
375                     System.out.println("Error msg: " + e.getMessage());
376                 } catch (Exception e) {
377                     System.out.println("Error adding data to registry");
378                     System.out.println("Error msg: " + e.getMessage());
379                 }
380 
381                 if (cir != null) {
382                     Enumeration jarInfoEnum = cir.getConverterInfoEnumeration();
383                     try {
384                         ConverterInfoMgr.addPlugIn(jarInfoEnum);
385                     } catch (Exception e) {
386                         System.out.println("Error adding data to registry");
387                         System.out.println("Error msg: " + e.getMessage());
388                     }
389                 }
390 
391             // Unload by Display Name or Jarfile
392             //
393 	    } else if (c == 'T') {
394 		if (validate== true){
395 		    System.out.println("Validation switched off");
396 		    validate=false;
397 		}else{
398 		    System.out.println("Validation switched on");
399 		    validate=true;
400 		}
401             } else if (c == 'D' || c == 'J') {
402 
403                 if (c == 'D') {
404                    System.out.println("Enter display name: ");
405                 } else {
406                    System.out.println("Enter path to jarfile: ");
407                 }
408 
409                 try
410                 {
411                     String name = br.readLine().trim();
412                     boolean rc = false;
413 
414                     if (c == 'D') {
415                         rc = ConverterInfoMgr.removeByName(name);
416                     } else {
417                         rc = ConverterInfoMgr.removeByJar(name);
418                     }
419 
420                     if (rc == true) {
421                         System.out.println("Remove successful.");
422                     } else {
423                         System.out.println("Remove failed.");
424                     }
425 
426                 } catch (Exception e) {
427                     System.out.println("Error removing value from registry");
428                     System.out.println("Error msg: " + e.getMessage());
429                 }
430 
431             // Find Office Mime
432             //
433             } else if (c == 'F' || c == 'C') {
434 
435                 String findMimeOne = null;
436                 String findMimeTwo = null;
437 
438                 if (c == 'F') {
439                     System.out.println("Enter device mime: ");
440                 } else {
441                     System.out.println("Enter device from mime: ");
442                 }
443 
444                 try {
445                     findMimeOne = br.readLine().trim();
446                 } catch (Exception e) {
447                     System.out.println("Error adding data to registry");
448                     System.out.println("Error msg: " + e.getMessage());
449                 }
450 
451                 if (c == 'F') {
452                     System.out.println("Enter office mime: ");
453                 } else {
454                     System.out.println("Enter device to mime: ");
455                 }
456 
457                 try {
458                     findMimeTwo = br.readLine().trim();
459                 } catch (Exception e) {
460                     System.out.println("Error adding data to registry");
461                     System.out.println("Error msg: " + e.getMessage());
462                 }
463 
464                 if (c == 'F') {
465                     ConverterInfo foundInfo = ConverterInfoMgr.findConverterInfo(findMimeOne, findMimeTwo);
466                     if (foundInfo != null) {
467                         System.out.println("    Found ConverterInfo");
468                         System.out.println("    DisplayName  : " + foundInfo.getDisplayName());
469                     } else {
470                         System.out.println("    Did not find ConverterInfo");
471                     }
472                 } else {
473                     ConverterInfo[] foundInfo = ConverterInfoMgr.findConverterInfoChain(findMimeOne,
474                         findMimeTwo);
475                     if (foundInfo[0] != null && foundInfo[1] != null ) {
476                         System.out.println("    Found ConverterInfo Chain");
477                         System.out.println("    DisplayName  : " + foundInfo[0].getDisplayName());
478                         System.out.println("    DisplayName  : " + foundInfo[1].getDisplayName());
479                     } else {
480                         System.out.println("    Did not find ConverterInfo");
481                     }
482                 }
483 
484             // View
485             //
486             } else if (c == 'V') {
487 
488                 Enumeration ciEnum = ConverterInfoMgr.getConverterInfoEnumeration();
489 
490                 int ciCnt = 0;
491                 while (ciEnum.hasMoreElements())
492                 {
493                     System.out.println("");
494                     System.out.println("  Displaying converter number " + ciCnt);
495                     ConverterInfo converterInfo = (ConverterInfo)ciEnum.nextElement();
496                     System.out.println("    DisplayName  : " + converterInfo.getDisplayName());
497                     System.out.println("    JarFile      : " + converterInfo.getJarName());
498                     System.out.println("    Description  : " + converterInfo.getDescription());
499                     System.out.println("    Version      : " + converterInfo.getVersion());
500                     System.out.println("    OfficeMime   : " + converterInfo.getOfficeMime());
501                     Enumeration fromEnum = converterInfo.getDeviceMime();
502                     int feCnt = 1;
503                     while (fromEnum.hasMoreElements())
504                     {
505                         System.out.println("    DeviceMime   : (#" + feCnt + ") : " +
506                             (String)fromEnum.nextElement());
507                         feCnt++;
508                     }
509                     if (feCnt == 1) {
510                         System.out.println("    DeviceMime   : None specified");
511                     }
512 
513                     System.out.println("    Vendor       : " + converterInfo.getVendor());
514                     System.out.println("    ClassImpl    : " + converterInfo.getClassImpl());
515                     System.out.println("    XsltSerial   : " + converterInfo.getXsltSerial());
516 		    System.out.println("    XsltDeserial : " + converterInfo.getXsltDeserial());
517 		    System.out.println("    Serialize    : " + converterInfo.canSerialize());
518                     System.out.println("    Deserialize  : " + converterInfo.canDeserialize());
519                     System.out.println("    Merge        : " + converterInfo.canMerge());
520                     ciCnt++;
521                 }
522 
523                 if (ciCnt == 0) {
524                     System.out.println("No converters registered");
525                 }
526             } else {
527                 System.out.println("Invalid input");
528             }
529         }
530     }
531 }
532 
533