summaryrefslogtreecommitdiffstats
path: root/xmerge/source/xmerge/java/org/openoffice/xmerge/util/registry
diff options
context:
space:
mode:
Diffstat (limited to 'xmerge/source/xmerge/java/org/openoffice/xmerge/util/registry')
-rw-r--r--xmerge/source/xmerge/java/org/openoffice/xmerge/util/registry/ConverterInfo.java406
-rw-r--r--xmerge/source/xmerge/java/org/openoffice/xmerge/util/registry/ConverterInfoMgr.java477
-rw-r--r--xmerge/source/xmerge/java/org/openoffice/xmerge/util/registry/ConverterInfoReader.java245
-rw-r--r--xmerge/source/xmerge/java/org/openoffice/xmerge/util/registry/RegistryException.java38
-rw-r--r--xmerge/source/xmerge/java/org/openoffice/xmerge/util/registry/package-info.java59
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;