1 /*
   2  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 /*
   5  * Licensed to the Apache Software Foundation (ASF) under one or more
   6  * contributor license agreements.  See the NOTICE file distributed with
   7  * this work for additional information regarding copyright ownership.
   8  * The ASF licenses this file to You under the Apache License, Version 2.0
   9  * (the "License"); you may not use this file except in compliance with
  10  * the License.  You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 package org.apache.qetest.xslwrapper;
  21 
  22 import java.lang.reflect.Field;
  23 import java.util.Enumeration;
  24 import java.util.Properties;
  25 
  26 import javax.xml.transform.ErrorListener;
  27 import javax.xml.transform.Transformer;
  28 import javax.xml.transform.TransformerFactory;
  29 import javax.xml.transform.URIResolver;
  30 
  31 /**
  32  * Cheap-o utilities for Trax*Wrapper implementations.
  33  *
  34  */
  35 public abstract class TraxWrapperUtils {
  36 
  37     /**
  38      * Get a generic description of the TrAX related info.
  39      *
  40      * @return Properties block with basic info about any TrAX implementing
  41      * processor, plus specific version information about Xalan-J 2.x or
  42      * Xerces-J 1.x if found.
  43      */
  44     public static Properties getTraxInfo() {
  45         Properties p = new Properties();
  46         p.put("traxwrapper.api", "trax");
  47         p.put("traxwrapper.language", "java");
  48         try {
  49             Properties sysProps = System.getProperties();
  50             p.put("traxwrapper.jaxp.transform",
  51                     sysProps.getProperty("javax.xml.transform.TransformerFactory", "unset"));
  52             p.put("traxwrapper.jaxp.parser.dom",
  53                     sysProps.getProperty("javax.xml.parsers.DocumentBuilderFactory", "unset"));
  54             p.put("traxwrapper.jaxp.parser.sax",
  55                     sysProps.getProperty("javax.xml.parsers.SAXParserFactory", "unset"));
  56         } /* In case we're in an Applet */
  57         catch (SecurityException ignore) { /* no-op, ignore */ }
  58 
  59         // Look for some Xalan/Xerces specific version info
  60         try {
  61             Class clazz = Class.forName("org.apache.xerces.framework.Version");
  62             // Found 1.x, grab it's version fields
  63             Field f = clazz.getField("fVersion");
  64             p.put("traxwrapper.xerces.version", (String) f.get(null));
  65         } catch (ClassNotFoundException | IllegalAccessException 
  66             | IllegalArgumentException | NoSuchFieldException 
  67             | SecurityException ignore) {}
  68  
  69         try {
  70             Class clazz = Class.forName("org.apache.xalan.processor.XSLProcessorVersion");
  71             Field f = clazz.getField("S_VERSION");
  72             p.put("traxwrapper.xalan.version", (String) f.get(null));
  73         } catch (ClassNotFoundException | IllegalAccessException 
  74             | IllegalArgumentException | NoSuchFieldException 
  75             | SecurityException ignore) {}
  76 
  77         return p;
  78     }
  79 
  80     /**
  81      * Apply specific Attributes to a TransformerFactory OR Transformer, OR call
  82      * specific setFoo() API's on a TransformerFactory OR Transformer.
  83      *
  84      * Filters on hash keys.startsWith("Processor.setAttribute"). Most Attributes
  85      * are simply passed to factory.setAttribute(), however certain special
  86      * cases are handled: setURIResolver, setErrorListener. Exceptions thrown by
  87      * underlying transformer are propagated.
  88      *
  89      * This takes an Object so that an underlying worker method can process
  90      * either a TransformerFactory or a Transformer.
  91      *
  92      * @param setPropsOn
  93      * @param attrs potential attributes to set.
  94      */
  95     public static void setAttributes(Object setPropsOn,
  96             Properties attrs) throws IllegalArgumentException {
  97         if ((null == setPropsOn) || (null == attrs)) {
  98             return;
  99         }
 100 
 101         Enumeration attrKeys;
 102         try {
 103             // Attempt to use as a Properties block..
 104             attrKeys = attrs.propertyNames();
 105         } catch (ClassCastException cce) {
 106             // .. but fallback to get as Hashtable instead
 107             attrKeys = attrs.keys();
 108         }
 109 
 110         while (attrKeys.hasMoreElements()) {
 111             String key = (String) attrKeys.nextElement();
 112             // Only attempt to set the attr if it matches our marker
 113             if ((null != key)
 114                     && (key.startsWith(TransformWrapper.SET_PROCESSOR_ATTRIBUTES))) {
 115                 Object value;
 116                 try {
 117                     // Attempt to use as a Properties block..
 118                     value =  attrs.getProperty(key);
 119                     // But, if null, then try getting as hash anyway
 120                     if (null == value) {
 121                         value = attrs.get(key);
 122                     }
 123                 } catch (ClassCastException cce) {
 124                     // .. but fallback to get as Hashtable instead
 125                     value = attrs.get(key);
 126                 }
 127                 // Strip off our marker for the property name
 128                 String processorKey = key.substring(TransformWrapper.SET_PROCESSOR_ATTRIBUTES.length());
 129                 // Ugly, but it works -sc
 130                 if (setPropsOn instanceof TransformerFactory) {
 131                     setAttribute((TransformerFactory) setPropsOn, processorKey, value);
 132                 } else if (setPropsOn instanceof Transformer) {
 133                     setAttribute((Transformer) setPropsOn, processorKey, value);
 134                 }
 135             }
 136         }
 137 
 138     }
 139 
 140     /**
 141      * Token specifying a call to setURIResolver.
 142      */
 143     private final static String SET_URI_RESOLVER = "setURIResolver";
 144 
 145     /**
 146      * Token specifying a call to setErrorListener.
 147      */
 148     private final static String SET_ERROR_LISTENER = "setErrorListener";
 149 
 150     /**
 151      * Apply specific Attributes to a TransformerFactory OR call specific
 152      * setFoo() API's on a TransformerFactory.
 153      *
 154      * Filters on keys.startsWith("Processor.setAttribute.") Most Attributes
 155      * are simply passed to factory.setAttribute(), however certain special
 156      * cases are handled: setURIResolver, setErrorListener. Exceptions thrown by
 157      * underlying transformer are propagated.
 158      *
 159      * @see setAttribute(Transformer, String, Object)
 160      * @param factory TransformerFactory to call setAttributes on.
 161      * @param key specific attribute or special case attribute.
 162      * @param value to set for key.
 163      */
 164     private static void setAttribute(TransformerFactory factory,
 165             String key, Object value) throws IllegalArgumentException {
 166         if ((null == factory) || (null == key)) {
 167             return;
 168         }
 169 
 170         // Note: allow exceptions to propagate here
 171         // Check if this is a special case to call a specific
 172         //  API, or the general case to call setAttribute(key...)
 173         switch(key) {
 174             case SET_URI_RESOLVER:
 175                 factory.setURIResolver((URIResolver) value);
 176                 break;
 177             case SET_ERROR_LISTENER:
 178                 factory.setErrorListener((ErrorListener) value);;
 179                 break;
 180             default:
 181                 // General case; just call setAttribute
 182                 factory.setAttribute(key, value);
 183                 break;                
 184         }
 185     }
 186 
 187     /**
 188      * Apply specific Attributes to a Transformer OR call specific setFoo()
 189      * API's on a Transformer.
 190      *
 191      * Filters on keys.startsWith("Processor.setAttribute.") Only certain
 192      * special cases are handled: setURIResolver, setErrorListener. Exceptions
 193      * thrown by underlying transformer are propagated.
 194      *
 195      * @see setAttribute(TransformerFactory, String, Object)
 196      * @param factory TransformerFactory to call setAttributes on.
 197      * @param key specific attribute or special case attribute.
 198      * @param value to set for key.
 199      */
 200     private static void setAttribute(Transformer transformer,
 201             String key, Object value) throws IllegalArgumentException {
 202         if ((null == transformer) || (null == key)) {
 203             return;
 204         }
 205 
 206         // Note: allow exceptions to propagate here
 207         // Check if this is a special case to call a specific
 208         //  API, or the general case to call setAttribute(key...)
 209         switch(key) {
 210             case SET_URI_RESOLVER:
 211                 transformer.setURIResolver((URIResolver) value);
 212                 break;
 213             case SET_ERROR_LISTENER:
 214                 transformer.setErrorListener((ErrorListener) value);
 215                 break;
 216         }
 217     }
 218 }