diff options
Diffstat (limited to 'xmerge/source/xmerge/java/org/openoffice/xmerge/util/registry')
5 files changed, 1225 insertions, 0 deletions
diff --git a/xmerge/source/xmerge/java/org/openoffice/xmerge/util/registry/ConverterInfo.java b/xmerge/source/xmerge/java/org/openoffice/xmerge/util/registry/ConverterInfo.java new file mode 100644 index 000000000..2190ab27c --- /dev/null +++ b/xmerge/source/xmerge/java/org/openoffice/xmerge/util/registry/ConverterInfo.java @@ -0,0 +1,406 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +package org.openoffice.xmerge.util.registry; + +import java.lang.reflect.Constructor; +import java.net.URL; +import java.net.URLClassLoader; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.Iterator; + +import org.openoffice.xmerge.DocumentDeserializerFactory; +import org.openoffice.xmerge.DocumentMergerFactory; +import org.openoffice.xmerge.DocumentSerializerFactory; +import org.openoffice.xmerge.PluginFactory; + +/** + * Class for storing the information about a converter plug-in. + */ +public class ConverterInfo { + + /** Keep track of the valid Office mime types. */ + private static final String[] validOfficeTypes = new String[] { + // This needs to be updated to reflect all valid office types. + "staroffice/sxw", + "staroffice/sxc" + }; + + private final String piJarName; + private final String piOfficeMime; + private final ArrayList<String> piDeviceMime; + private final String piDisplayName; + private final String piDescription; + private final String piVersion; + private final String piVendor; + private final String piClassImpl; + private String piXsltSerial; + private String piXsltDeserial; + private boolean piCanSerialize = false; + private boolean piCanDeserialize = false; + private boolean piCanMerge = false; + private final ClassLoader piClassLoader; + private PluginFactory piPluginFactory; + + + /** + * The constructor builds a ConverterInfo structure. + * + * @param jarName The URL of the jarfile. + * @param officeMime The office mime-type. + * @param deviceMime The device mime-type. + * @param displayName The display name. + * @param description The description. + * @param version The version. + * @param vendor The vendor name. + * @param impl The implementation class name of + * {@code PluginFactory}. + * @param xsltSerial The URL of the serializer XSL stylesheet + * @param xsltDeserial The URL of the deserializer XSL stylesheet + * + * @throws RegistryException If {@code ci} cannot be loaded. + */ + public ConverterInfo(String jarName, String officeMime, + ArrayList<String> deviceMime, String displayName, + String description, String version, String vendor, + String impl,String xsltSerial, String xsltDeserial) + throws RegistryException { + + if (!isValidOfficeType(officeMime.trim())) { + RegistryException re = new RegistryException( "Invalid office type"); + throw re; + } + + piJarName = jarName.trim(); + piOfficeMime = officeMime.trim(); + piDeviceMime = deviceMime; + piDisplayName = displayName.trim(); + piDescription = description.trim(); + piVersion = version.trim(); + piVendor = vendor.trim(); + piXsltSerial = xsltSerial.trim(); + piXsltDeserial= xsltDeserial.trim(); + piClassImpl = impl.trim(); + piClassLoader = this.getClass().getClassLoader(); + + // Get instance of the PluginFactory. + + try { + final URL jarURL = new URL(jarName); + final URL[] urls = new URL[] { jarURL }; + URLClassLoader loader = AccessController.doPrivileged( + new PrivilegedAction<URLClassLoader>() { + public URLClassLoader run() { + return new URLClassLoader(urls, piClassLoader); + } + }); + Class<?> clas = loader.loadClass(piClassImpl); + Class<?>[] argumentTypes = { org.openoffice.xmerge.util.registry.ConverterInfo.class }; + Constructor<?> construct = clas.getConstructor(argumentTypes); + + Object[] arguments = { this }; + piPluginFactory = ( PluginFactory ) construct.newInstance(arguments); + + // See which interfaces the plug-in PluginFactory supports. + + Class<?>[] cl = piPluginFactory.getClass().getInterfaces(); + for (int i=0; i < cl.length; i++) { + + if (cl[i].getName().equals("org.openoffice.xmerge.DocumentSerializerFactory")) { + piCanSerialize = true; + } + if (cl[i].getName().equals("org.openoffice.xmerge.DocumentDeserializerFactory")) { + piCanDeserialize = true; + } + if (cl[i].getName().equals("org.openoffice.xmerge.DocumentMergerFactory")) { + piCanMerge = true; + } + } + + } catch (Exception e) { + throw new RegistryException( + "Class implementation of the plug-in cannot be loaded.", e); + } + } + + /** + * The constructor builds a ConverterInfo structure. + * + * @param jarName The URL of the jarfile. + * @param officeMime The office mime-type. + * @param deviceMime The device mime-type. + * @param displayName The display name. + * @param description The description. + * @param version The version. + * @param vendor The vendor name. + * @param impl The implementation class name of + * {@code PluginFactory}. + * + * @throws RegistryException If {@code ci} cannot be loaded. + */ + public ConverterInfo(String jarName, String officeMime, + ArrayList<String> deviceMime, String displayName, String description, + String version, String vendor, String impl) + throws RegistryException { + + if (officeMime == null || displayName == null || description == null || + version == null || vendor == null || impl == null) + throw new IllegalArgumentException("arguments unexpected null"); + + if (!isValidOfficeType(officeMime.trim())) { + RegistryException re = new RegistryException( + "Invalid office type"); + throw re; + } + + piJarName = jarName.trim(); + piOfficeMime = officeMime.trim(); + piDeviceMime = deviceMime; + piDisplayName = displayName.trim(); + piDescription = description.trim(); + piVersion = version.trim(); + piVendor = vendor.trim(); + piClassImpl = impl.trim(); + piClassLoader = this.getClass().getClassLoader(); + + // Get instance of the PluginFactory. + + try { + final URL jarURL = new URL(jarName); + final URL[] urls = new URL[] { jarURL }; + URLClassLoader loader = AccessController.doPrivileged( + new PrivilegedAction<URLClassLoader>() { + public URLClassLoader run() { + return new URLClassLoader(urls, piClassLoader); + } + }); + Class<?> clas = loader.loadClass(piClassImpl); + Class<?>[] argumentTypes = { org.openoffice.xmerge.util.registry.ConverterInfo.class }; + Constructor<?> construct = clas.getConstructor(argumentTypes); + + Object[] arguments = { this }; + piPluginFactory = ( PluginFactory ) construct.newInstance(arguments); + + // See which interfaces the plug-in PluginFactory supports. + + Class<?>[] cl = piPluginFactory.getClass().getInterfaces(); + for (int i=0; i < cl.length; i++) { + + if (cl[i].getName().equals("org.openoffice.xmerge.DocumentSerializerFactory")) { + piCanSerialize = true; + } + if (cl[i].getName().equals("org.openoffice.xmerge.DocumentDeserializerFactory")) { + piCanDeserialize = true; + } + if (cl[i].getName().equals("org.openoffice.xmerge.DocumentMergerFactory")) { + piCanMerge = true; + } + } + + } catch (Exception e) { + throw new RegistryException( + "Class implementation of the plug-in cannot be loaded.", e); + } + } + + /** + * Returns an instance of the {@code DocumentDeserializerFactory} interface. + * + * @return instance of the {@code DocumentDeserializer} for this + * {@code ConverterInfo}. + */ + public DocumentSerializerFactory getDocSerializerFactory() { + return (DocumentSerializerFactory)piPluginFactory; + } + + /** + * Returns an instance of the {@code DocumentSerializerFactory} interface. + * + * @return instance of the {@code DocumentSerializer} for this + * {@code ConverterInfo}. + */ + public DocumentDeserializerFactory getDocDeserializerFactory() { + return (DocumentDeserializerFactory)piPluginFactory; + } + + /** + * Returns an instance of the DocumentMergerFactory interface. + * + * @return instance of the {@code DocumentMergerFactory} for this + * {@code ConverterInfo}. + */ + public DocumentMergerFactory getDocMergerFactory() { + return (DocumentMergerFactory)piPluginFactory; + } + + /** + * Returns the jar file name. + * + * @return The jar file name, {@code null} if none exists. + */ + public String getJarName() { + return piJarName; + } + + /** + * Returns the office mime-type. + * + * @return The office mime-type, {@code null} if none exists. + */ + public String getOfficeMime() { + return piOfficeMime; + } + + /** + * Returns an {@code Enumeration} of {@code String} objects indicating the + * device mime-type. + * + * @return An {@code Enumeration} of {@code String} objects indicating the + * device mime-type. + */ + public Iterator<String> getDeviceMime() { + return piDeviceMime.iterator(); + } + + /** + * Returns the display name. + * + * @return The display name, {@code null} if none exists. + */ + public String getDisplayName() { + return piDisplayName; + } + + /** + * Returns the description. + * + * @return The description, {@code null} if none exists. + */ + public String getDescription() { + return piDescription; + } + + /** + * Returns the version. + * + * @return The version, {@code null} if none exists. + */ + public String getVersion() { + return piVersion; + } + + /** + * Returns the vendor name. + * + * @return The vendor name, {@code null} if none exists. + */ + public String getVendor() { + return piVendor; + } + + /** + * Returns the implementation class name of PluginFactory. + * + * @return The implementation class name of {@code PluginFactory}, + * {@code null} if none exists. + */ + public String getClassImpl() { + return piClassImpl; + } + + /** + * Returns the {@code PluginFactory} instance for this plug-in. + * + * @return The {@code PluginFactory} instance for this plug-in. + */ + public PluginFactory getPluginFactory() { + return piPluginFactory; + } + + /** + * Returns {@code true} if this plug-in has a serializer, {@code false} + * otherwise. + * + * @return {@code true} if this plug-in has a serializer, {@code false} + * otherwise. + */ + public boolean canSerialize() { + return piCanSerialize; + } + + /** + * Returns {@code true} if this plug-in has a deserializer, {@code false} + * otherwise. + * + * @return {@code true} if this plug-in has a deserializer, {@code false} + * otherwise. + */ + public boolean canDeserialize() { + return piCanDeserialize; + } + + /** + * Returns {@code true} if this plug-in has a merger, {@code false} + * otherwise. + * + * @return {@code true} if this plug-in has a merger, {@code false} + * otherwise. + */ + public boolean canMerge() { + return piCanMerge; + } + + /** + * Returns {@code true} if the officeMime is a valid Office mime type. + * + * @return {@code true} if the officeMime is a valid Office mime type. + */ + public static boolean isValidOfficeType(String officeMime) { + + boolean rc = false; + for (String validOfficeType : validOfficeTypes) { + if (officeMime.equals(validOfficeType)) { + rc = true; + } + } + + return rc; + } + + /** + * Returns a {@code String} containing the Xslt stylesheet URL that is to be + * used by the Xslt Plug-in Serializer. + * + * @return {@code String}. + */ + public String getXsltSerial() { + return piXsltSerial; + } + + /** + * Returns a {@code String} containing the xslt stylesheet URL that is to be + * used by the Xslt Plug-in Deserializer. + * + * @return {@code String}. + */ + public String getXsltDeserial() { + return piXsltDeserial; + } +} diff --git a/xmerge/source/xmerge/java/org/openoffice/xmerge/util/registry/ConverterInfoMgr.java b/xmerge/source/xmerge/java/org/openoffice/xmerge/util/registry/ConverterInfoMgr.java new file mode 100644 index 000000000..9cea2df38 --- /dev/null +++ b/xmerge/source/xmerge/java/org/openoffice/xmerge/util/registry/ConverterInfoMgr.java @@ -0,0 +1,477 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +package org.openoffice.xmerge.util.registry; + +import java.util.*; +import java.io.*; + +/** + * Manages the converter plug-ins that are currently active. + * + * <p>This class allows plug-ins to be added or removed dynamically.</p> + * + * <p>This class is a singleton (static) class, so that only one manager can + * exist at a time. It is final, so it may not be sub-classed.</p> + */ +public final class ConverterInfoMgr { + + private static final ArrayList<ConverterInfo> converterInfoList = new ArrayList<ConverterInfo>(); + + /** + * Adds a converter plug-in to the registry. + * + * <p>The {@code ConverterInfo} must have a unique DisplayName and must have + * non-null values for DisplayName, ClassImpl, OfficeMime, and DeviceMime.</p> + * + * @param ci A {@code ConverterInfo} object describing a plug-in. + * + * @throws RegistryException If the {@code ConverterInfo} is not valid. + */ + private static void addPlugIn(ConverterInfo ci) throws RegistryException { + + // Validate + if (ci.getDisplayName() == null) { + RegistryException re = new RegistryException( + "Converter must have valid name."); + throw re; + } + if (ci.getClassImpl() == null) { + RegistryException re = new RegistryException( + "Converter must have valid class implementation specified."); + throw re; + } + if (ci.getOfficeMime() == null) { + RegistryException re = new RegistryException( + "Converter must have valid office mime specified."); + throw re; + } + if (! ci.getDeviceMime().hasNext()) { + RegistryException re = new RegistryException( + "Converter must have valid device mime specified."); + throw re; + } + + // Verify there is no converter with the same Display Name in the + // registry. + for (ConverterInfo converterInfo : converterInfoList) { + if (ci.getDisplayName().equals(converterInfo.getDisplayName())) { + RegistryException re = new RegistryException( + "Converter with specified display name already exists."); + throw re; + } + } + + // Since this is adding to a static Vector, make sure this add method + // call is synchronized. + synchronized (converterInfoList) { + converterInfoList.add(ci); + } + } + + /** + * Adds a list of converter plug-ins to the registry. + * + * <p>Each {@code ConverterInfo} in the list must have a unique DisplayName + * and must have non-null values for DisplayName, ClassImpl, OfficeMime, and + * DeviceMime.</p> + * + * @param jarEnum An {@code Enumeration} of {@code ConverterInfo} objects + * describing one or more plug-in(s). + * + * @throws RegistryException If a {@code ConverterInfo} in the + * {@code Vector} is not valid. + */ + public static void addPlugIn(Iterator<ConverterInfo> jarEnum) + throws RegistryException { + + while (jarEnum.hasNext()) { + ConverterInfo converterInfo = jarEnum.next(); + addPlugIn(converterInfo); + } + } + + /** + * Returns an {@code Enumeration} of registered {@code ConverterInfo} objects. + * + * @return An {@code Enumeration} containing the currently registered + * {@code ConverterInfo} objects, an empty {@code Vector} if none + * exist. + */ + private static Iterator<ConverterInfo> getConverterInfoEnumeration() { + return converterInfoList.iterator(); + } + + /** + * Removes any {@code ConverterInfo} object from the registry that have the + * specified jar name value. + * + * @param jar The name of the jarfile. + * + * @return {@code true} if a {@code ConverterInfo} object was removed, + * {@code false} otherwise. + */ + public static boolean removeByJar(String jar) { + + boolean rc = false; + + for (Iterator<ConverterInfo> it = converterInfoList.iterator(); it.hasNext();) { + ConverterInfo converterInfo = it.next(); + if (jar.equals(converterInfo.getJarName())) { + it.remove(); + rc = true; + } + } + return rc; + } + + /** + * Removes any {@code ConverterInfo} object from the registry that have the + * specified display name value. + * + * @param name The display name. + * + * @return {@code true} if a {@code ConverterInfo} object was removed, + * {@code false} otherwise. + */ + private static boolean removeByName(String name) { + + boolean rc = false; + + for (Iterator<ConverterInfo> it = converterInfoList.iterator(); it.hasNext();) { + ConverterInfo converterInfo = it.next(); + if (name.equals(converterInfo.getDisplayName())) { + it.remove(); + rc = true; + } + } + return rc; + } + + /** + * Returns the {@code ConverterInfo} object that supports the specified + * device/office mime type conversion. + * + * <p>If there are multiple {@code ConverterInfo} objects registered that + * support this conversion, only the first is returned.</p> + * + * @param deviceMime The device mime. + * @param officeMime The office mime. + * + * @return The first plug-in that supports the specified conversion. + */ + public static ConverterInfo findConverterInfo(String deviceMime, String officeMime) { + + if (deviceMime == null || + !ConverterInfo.isValidOfficeType(officeMime)) { + return null; + } + + // Loop over elements comparing with deviceFromMime + for (ConverterInfo converterInfo : converterInfoList) { + String toDeviceInfo = converterInfo.getOfficeMime(); + Iterator<String> fromEnum = converterInfo.getDeviceMime(); + + // Loop over the deviceMime types. + while (fromEnum.hasNext()) { + String fromDeviceInfo = fromEnum.next(); + if (deviceMime.trim().equals(fromDeviceInfo) && + officeMime.trim().equals(toDeviceInfo)) { + return converterInfo; + } + } + } + return null; + } + + /** + * Returns an array of two {@code ConverterInfo} objects that can be chained + * to perform the specified mime type conversion. + * + * <p>If there are multiple {@code ConverterInfo} objects that support this + * conversion, only the first is returned.</p> + * + * @param deviceFromMime The device from mime. + * @param deviceToMime The device to mime. + * + * @return An array of two {@code ConverterInfo} objects that can be chained + * to perform the specified conversion. + */ + private static ConverterInfo[] findConverterInfoChain(String deviceFromMime, String deviceToMime) { + + if (deviceFromMime == null || deviceToMime == null) { + return null; + } + + ConverterInfo[] converterInfo = new ConverterInfo[2]; + + // Loop over elements comparing with deviceFromMime + Iterator<ConverterInfo> cifEnum = converterInfoList.iterator(); + while (cifEnum.hasNext()) { + + converterInfo[0] = cifEnum.next(); + String fromOfficeInfo = converterInfo[0].getOfficeMime(); + Iterator<String> fromEnum = converterInfo[0].getDeviceMime(); + + // Loop over the deviceMime types looking for a deviceFromMime + // match. + while (fromEnum.hasNext()) { + String fromDeviceInfo = fromEnum.next(); + + if (deviceFromMime.trim().equals(fromDeviceInfo)) { + + // Found a match for deviceFrom. Now loop over the + // elements comparing with deviceToMime + Iterator<ConverterInfo> citEnum = converterInfoList.iterator(); + while (citEnum.hasNext()) { + + converterInfo[1] = citEnum.next(); + String toOfficeInfo = converterInfo[1].getOfficeMime(); + Iterator<String> toEnum = converterInfo[1].getDeviceMime(); + + // Loop over deviceMime types looking for a + // deviceToMime match. + while (toEnum.hasNext()) { + String toDeviceInfo = toEnum.next(); + if (deviceToMime.trim().equals(toDeviceInfo) && + fromOfficeInfo.equals(toOfficeInfo)) { + + // Found a match + return converterInfo; + } + } + } + } + } + } + return null; + } + + static String readLine(BufferedReader br) throws IOException{ + String ret = br.readLine(); + if (ret == null) { + throw new IOException("short read"); + } + return ret; + } + + /** + * Main to let the user specify what plug-ins to register from jarfiles and + * to display the currently registered plug-ins. + * + * @param args Not used. + */ + public static void main(String args[]) { + + ConverterInfoReader cir = null; + boolean validate = false; + InputStreamReader isr = new InputStreamReader(System.in); + BufferedReader br = new BufferedReader(isr); + char c = ' '; + + boolean exitFlag = false; + while (!exitFlag) { + + System.out.println("\nMenu:"); + System.out.println("(L)oad plug-ins from a jar file"); + System.out.println("(D)isplay name unload"); + System.out.println("(J)ar name unload"); + System.out.println("(F)ind ConverterInfo"); + System.out.println("(C)ind ConverterInfo chain"); + System.out.println("(V)iew plug-ins"); + System.out.println("(T)oggle Validation"); + System.out.println("(Q)uit\n"); + + try { + c = readLine(br).toUpperCase().trim().charAt(0); + } catch(Exception e) { + System.out.println("Invalid entry"); + System.out.println("Error msg: " + e.getMessage()); + continue; + } + + System.out.println(""); + + // Quit + if (c == 'Q') { + exitFlag = true; + + // Load by Jarfile + } else if (c == 'L') { + + System.out.println("Enter path to jarfile: "); + try { + String jarname = readLine(br).trim(); + cir = new ConverterInfoReader(jarname,validate); + } catch (RegistryException e) { + System.out.println("Cannot load plug-in ConverterFactory implementation."); + System.out.println("Error msg: " + e.getMessage()); + } catch (Exception e) { + System.out.println("Error adding data to registry"); + System.out.println("Error msg: " + e.getMessage()); + } + + if (cir != null) { + Iterator<ConverterInfo> jarInfoEnum = cir.getConverterInfoEnumeration(); + try { + ConverterInfoMgr.addPlugIn(jarInfoEnum); + } catch (Exception e) { + System.out.println("Error adding data to registry"); + System.out.println("Error msg: " + e.getMessage()); + } + } + + // Unload by Display Name or Jarfile + } else if (c == 'T') { + if (validate){ + System.out.println("Validation switched off"); + validate=false; + } else { + System.out.println("Validation switched on"); + validate=true; + } + } else if (c == 'D' || c == 'J') { + + if (c == 'D') { + System.out.println("Enter display name: "); + } else { + System.out.println("Enter path to jarfile: "); + } + + try { + String name = readLine(br).trim(); + boolean rc = false; + + if (c == 'D') { + rc = ConverterInfoMgr.removeByName(name); + } else { + rc = ConverterInfoMgr.removeByJar(name); + } + + if (rc) { + System.out.println("Remove successful."); + } else { + System.out.println("Remove failed."); + } + + } catch (Exception e) { + System.out.println("Error removing value from registry"); + System.out.println("Error msg: " + e.getMessage()); + } + + // Find Office Mime + + } else if (c == 'F' || c == 'C') { + + String findMimeOne = null; + String findMimeTwo = null; + + if (c == 'F') { + System.out.println("Enter device mime: "); + } else { + System.out.println("Enter device from mime: "); + } + + try { + findMimeOne = readLine(br).trim(); + } catch (Exception e) { + System.out.println("Error adding data to registry"); + System.out.println("Error msg: " + e.getMessage()); + } + + if (c == 'F') { + System.out.println("Enter office mime: "); + } else { + System.out.println("Enter device to mime: "); + } + + try { + findMimeTwo = readLine(br).trim(); + } catch (Exception e) { + System.out.println("Error adding data to registry"); + System.out.println("Error msg: " + e.getMessage()); + } + + if (c == 'F') { + ConverterInfo foundInfo = ConverterInfoMgr.findConverterInfo(findMimeOne, findMimeTwo); + if (foundInfo != null) { + System.out.println(" Found ConverterInfo"); + System.out.println(" DisplayName : " + foundInfo.getDisplayName()); + } else { + System.out.println(" Did not find ConverterInfo"); + } + } else { + ConverterInfo[] foundInfo = ConverterInfoMgr.findConverterInfoChain(findMimeOne, + findMimeTwo); + if (foundInfo != null && foundInfo[0] != null && foundInfo[1] != null ) { + System.out.println(" Found ConverterInfo Chain"); + System.out.println(" DisplayName : " + foundInfo[0].getDisplayName()); + System.out.println(" DisplayName : " + foundInfo[1].getDisplayName()); + } else { + System.out.println(" Did not find ConverterInfo"); + } + } + + // View + + } else if (c == 'V') { + + Iterator<ConverterInfo> ciEnum = ConverterInfoMgr.getConverterInfoEnumeration(); + + int ciCnt = 0; + while (ciEnum.hasNext()) + { + System.out.println(""); + System.out.println(" Displaying converter number " + ciCnt); + ConverterInfo converterInfo = ciEnum.next(); + System.out.println(" DisplayName : " + converterInfo.getDisplayName()); + System.out.println(" JarFile : " + converterInfo.getJarName()); + System.out.println(" Description : " + converterInfo.getDescription()); + System.out.println(" Version : " + converterInfo.getVersion()); + System.out.println(" OfficeMime : " + converterInfo.getOfficeMime()); + Iterator<String> fromEnum = converterInfo.getDeviceMime(); + int feCnt = 1; + while (fromEnum.hasNext()) + { + System.out.println(" DeviceMime : (#" + feCnt + ") : " + + fromEnum.next()); + feCnt++; + } + if (feCnt == 1) { + System.out.println(" DeviceMime : None specified"); + } + + System.out.println(" Vendor : " + converterInfo.getVendor()); + System.out.println(" ClassImpl : " + converterInfo.getClassImpl()); + System.out.println(" XsltSerial : " + converterInfo.getXsltSerial()); + System.out.println(" XsltDeserial : " + converterInfo.getXsltDeserial()); + System.out.println(" Serialize : " + converterInfo.canSerialize()); + System.out.println(" Deserialize : " + converterInfo.canDeserialize()); + System.out.println(" Merge : " + converterInfo.canMerge()); + ciCnt++; + } + + if (ciCnt == 0) { + System.out.println("No converters registered"); + } + } else { + System.out.println("Invalid input"); + } + } + } +} diff --git a/xmerge/source/xmerge/java/org/openoffice/xmerge/util/registry/ConverterInfoReader.java b/xmerge/source/xmerge/java/org/openoffice/xmerge/util/registry/ConverterInfoReader.java new file mode 100644 index 000000000..21831a691 --- /dev/null +++ b/xmerge/source/xmerge/java/org/openoffice/xmerge/util/registry/ConverterInfoReader.java @@ -0,0 +1,245 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +package org.openoffice.xmerge.util.registry; + +import java.io.*; +import java.util.*; +import java.util.jar.*; +import org.xml.sax.*; +import org.w3c.dom.*; +import javax.xml.parsers.*; +import java.net.URL; +import java.net.JarURLConnection; + +/** + * The {@code ConverterInfoReader} pulls a {@code META-INF/converter.xml} file + * out of a jar file and parses it, providing access to this information in a + * {@code Vector} of {@code ConverterInfo} objects. + */ +public class ConverterInfoReader { + + private static final String TAG_CONVERTER = "converter"; + private static final String ATTRIB_OFFICE_TYPE = "type"; + private static final String ATTRIB_VERSION = "version"; + private static final String TAG_NAME = "converter-display-name"; + private static final String TAG_DESC = "converter-description"; + private static final String TAG_VENDOR = "converter-vendor"; + private static final String TAG_CLASS_IMPL = "converter-class-impl"; + private static final String TAG_TARGET = "converter-target"; + private static final String ATTRIB_DEVICE_TYPE = "type"; + private static final String TAG_XSLT_DESERIAL = "converter-xslt-deserialize"; + private static final String TAG_XSLT_SERIAL = "converter-xslt-serialize"; + private final String jarfilename; + private final Document document; + private final ArrayList<ConverterInfo> converterInfoList; + + /** + * Constructor. + * + * <p>A jar file is passed in. The jar file is parsed and the {@code Vector} + * of {@code ConverterInfo} objects is built.</p> + * + * @param jar The URL of the jar file to process. + * @param shouldvalidate Boolean to enable or disable xml validation. + * + * @throws IOException If the jar file cannot be read or + * if the META-INF/converter.xml can + * not be read in the jar file. + * @throws ParserConfigurationException If the {@code DocumentBuilder} + * can not be built. + * @throws org.xml.sax.SAXException If the converter.xml file can not + * be parsed. + * @throws RegistryException If the {@code ConverterFactory} + * implementation of a plug-in cannot + * be loaded. + */ + public ConverterInfoReader(String jar,boolean shouldvalidate) throws IOException, + ParserConfigurationException, org.xml.sax.SAXException, + RegistryException { + + converterInfoList = new ArrayList<ConverterInfo>(); + jarfilename = jar; + + // Get Jar via URL + URL url = new URL("jar:" + jar + "!/META-INF/converter.xml"); + JarURLConnection jarConnection = (JarURLConnection)url.openConnection(); + JarEntry jarentry = jarConnection.getJarEntry(); + JarFile jarfile = jarConnection.getJarFile(); + + if (jarfile == null || jarentry == null) { + throw new IOException("Missing jar entry"); + } + + // Build the InputSource + InputStream istream = jarfile.getInputStream(jarentry); + InputSource isource = new InputSource(istream); + + // Get the DOM builder and build the document. + + DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); + + //DTD validation + + if (shouldvalidate) { + System.out.println("Validating xml..."); + builderFactory.setValidating(true); + } + + DocumentBuilder builder = builderFactory.newDocumentBuilder(); + document = builder.parse(isource); + + // Parse the document. + + parseDocument(); + } + + /** + * Loops over the <i>converter</i> {@code Node} in the converter.xml file + * and processes them. + * + * @throws RegistryException If the plug-in associated with a specific + * <i>converter</i> {@code Node} cannot be + * loaded. + */ + private void parseDocument() throws RegistryException { + + Node converterNode; + NodeList converterNodes = document.getElementsByTagName(TAG_CONVERTER); + + for (int i=0; i < converterNodes.getLength(); i++) { + converterNode = converterNodes.item(i); + if (converterNode.getNodeType() == Node.ELEMENT_NODE) { + parseConverterNode((Element)converterNode); + } + } + } + + /** + * Parses a <i>converter</i> node, pulling the information out of the + * {@code Node} and placing it in a {@code ConverterInfo} object, and adds + * that object to a {@code Vector} of {@code ConverterInfo} objects. + * + * @param e The {@code Element} corresponding to the <i>converter</i> + * XML tag. + * + * @throws RegistryException If the plug-in cannot be loaded. + */ + private void parseConverterNode(Element e) throws RegistryException { + + Element detailElement; + Node detailNode; + String elementTagName; + String officeMime = null; + ArrayList<String> deviceMime = new ArrayList<String>(); + String name = null; + String desc = null; + String version = null; + String vendor = null; + String classImpl = null; + String xsltSerial = null; + String xsltDeserial = null; + String temp; + + temp = e.getAttribute(ATTRIB_OFFICE_TYPE); + if (temp.length() != 0) { + officeMime = temp; + } + + temp = e.getAttribute(ATTRIB_VERSION); + if (temp.length() != 0) { + version = temp; + } + + NodeList detailNodes = e.getChildNodes(); + for (int i=0; i < detailNodes.getLength(); i++) { + + detailNode = detailNodes.item(i); + if (detailNode.getNodeType() == Node.ELEMENT_NODE) { + + detailElement = (Element)detailNode; + elementTagName = detailElement.getTagName(); + + if (TAG_NAME.equalsIgnoreCase(elementTagName)) { + name = getTextValue(detailElement); + } else if (TAG_DESC.equalsIgnoreCase(elementTagName)) { + desc = getTextValue(detailElement); + } else if (TAG_VENDOR.equalsIgnoreCase(elementTagName)) { + vendor = getTextValue(detailElement); + } else if (TAG_XSLT_SERIAL.equalsIgnoreCase(elementTagName)) { + xsltSerial = getTextValue(detailElement); + } else if (TAG_XSLT_DESERIAL.equalsIgnoreCase(elementTagName)) { + xsltDeserial = getTextValue(detailElement); + } else if (TAG_CLASS_IMPL.equalsIgnoreCase(elementTagName)) { + classImpl = getTextValue(detailElement); + } else if (TAG_TARGET.equalsIgnoreCase(elementTagName)) { + temp = detailElement.getAttribute(ATTRIB_DEVICE_TYPE); + if (temp.length() != 0) { + deviceMime.add(temp); + } + } + } + } + + ConverterInfo converterInfo; + if ((xsltSerial == null) || (xsltDeserial == null)) { + converterInfo = new ConverterInfo(jarfilename, + officeMime, deviceMime, name, + desc, version, vendor, classImpl); + } else { + converterInfo = new ConverterInfo(jarfilename, + officeMime, deviceMime, name, + desc, version, vendor, classImpl, + xsltSerial, xsltDeserial); + } + converterInfoList.add(converterInfo); + } + + /** + * Helper function to get the text value of an {@code Element}. + * + * @param e The {@code Element} to process. + * + * @return The text value of the {@code Element}. + */ + private String getTextValue(Element e) { + + NodeList tempNodes = e.getChildNodes(); + String text = null; + Node tempNode; + + for (int j=0; j < tempNodes.getLength(); j++) { + tempNode = tempNodes.item(j); + if (tempNode.getNodeType() == Node.TEXT_NODE) { + text = tempNode.getNodeValue().trim(); + break; + } + } + + return text; + } + + /** + * Returns an {@code Enumeration} of {@code ConverterInfo} objects. + * + * @return An {@code Enumeration} of {@code ConverterInfo} objects. + */ + public Iterator<ConverterInfo> getConverterInfoEnumeration() { + return converterInfoList.iterator(); + } +} diff --git a/xmerge/source/xmerge/java/org/openoffice/xmerge/util/registry/RegistryException.java b/xmerge/source/xmerge/java/org/openoffice/xmerge/util/registry/RegistryException.java new file mode 100644 index 000000000..6452256d2 --- /dev/null +++ b/xmerge/source/xmerge/java/org/openoffice/xmerge/util/registry/RegistryException.java @@ -0,0 +1,38 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +package org.openoffice.xmerge.util.registry; + +/** + * This {@code Exception} is thrown by converter registry algorithms. + */ +public class RegistryException extends Exception { + + /** + * Exception thrown by merge algorithms. + * + * @param message Message to be included in the {@code Exception}. + */ + public RegistryException(String message) { + super(message); + } + + public RegistryException(String message, Throwable cause) { + super(message, cause); + } +}
\ No newline at end of file diff --git a/xmerge/source/xmerge/java/org/openoffice/xmerge/util/registry/package-info.java b/xmerge/source/xmerge/java/org/openoffice/xmerge/util/registry/package-info.java new file mode 100644 index 000000000..8634ab0a9 --- /dev/null +++ b/xmerge/source/xmerge/java/org/openoffice/xmerge/util/registry/package-info.java @@ -0,0 +1,59 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +/** + * Provides an interface for plug-in registration. + * + * <p>Each plug-in must have a corresponding Plug-in Configuration XML File + * which is named converter.xml. If the plug-in is stored in a jarfile, this + * converter.xml file is typically stored in the following location in the + * jarfile:</p> + * + * <blockquote>META-INF/converter.xml</blockquote> + * + * <p>The Plug-in Configuration XML File must validate against the converter.dtd + * file provided with this package. Since a jarfile can contain multiple + * plug-ins, this DTD supports specifying multiple plug-ins per jarfile. Please + * refer to the SDK document for more information about how to implement a + * Plug-in Configuration XML File for a specific plug-in.</p> + * + * <p>All information in the Plug-in Configuration XML File is bundled into one + * or more {@code ConverterInfo} object. The {@code ConverterInfoReader} object + * is used to build a {@code Vector} of {@code ConverterInfo} objects from a + * jarfile.</p> + * + * <p>The {@code ConverterInfoMgr} manages the registry of {@code ConverterInfo}. + * It is a singleton class, so that only one registry manager will ever exist. + * It is the client program's responsibility to register {@code ConverterInfo} + * objects that correspond to the plug-ins that are to be used.</p> + * + * <h2>TODO/IDEAS list</h2> + * <ol> + * <li>The {@code ConverterInfo} object could contain + * {@code org.w3c.dom.Document} fragments that are accessed in a generic + * fashion rather than get/set methods for each item in the DTD. This would + * provide a more flexible approach, especially for adding custom tags to a + * specific Plug-in Configuration XML file (tags that are only used by its + * associated plug-in).</li> + * <li>{@code ConverterInfo} should allow the merge/serialize/deserialize logic + * to be included in separate plug-ins, if desired.</li> + * <li>{@code ConverterInfoMgr} could use the Java Activation Framework (JAF) + * to manage registration.</li> + * </ol> + */ +package org.openoffice.xmerge.util.registry; |