public class ShortcutsOptionPane extends AbstractOptionPane
{
	//{{{ ShortcutsOptionPane constructor
	public ShortcutsOptionPane()
	{
		super("shortcuts");
	} //}}}

	//{{{ _init() method
	@Override
	protected void _init()
	{
		allBindings = new Vector<KeyBinding>();

		setLayout(new BorderLayout(12,12));

		initModels();

		selectModel = new JComboBox(models);
		selectModel.addActionListener(new ActionHandler());
		selectModel.setToolTipText(jEdit.getProperty("options.shortcuts.select.tooltip"));
		Box north = Box.createHorizontalBox();
		north.add(new JLabel(jEdit.getProperty(
			"options.shortcuts.select.label")));
		north.add(Box.createHorizontalStrut(6));
		north.add(selectModel);

		filterTF = new JTextField(40);
		filterTF.setToolTipText(jEdit.getProperty("options.shortcuts.filter.tooltip"));
		filterTF.getDocument().addDocumentListener(new DocumentListener()
		{
			public void changedUpdate(DocumentEvent e)
			{
				setFilter();
			}

			public void insertUpdate(DocumentEvent e)
			{
				setFilter();
			}

			public void removeUpdate(DocumentEvent e)
			{
				setFilter();
			}
		});
		JButton clearButton = new JButton(jEdit.getProperty(
				"options.shortcuts.clear.label"));
		clearButton.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent arg0)
			{
				filterTF.setText("");
				filterTF.requestFocus();
			}
		});

		JPanel filterPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
		filterPanel.add(new JLabel(jEdit.getProperty("options.shortcuts.filter.label")));
		filterPanel.add(filterTF);
		filterPanel.add(clearButton);

		keyTable = new JTable(filteredModel);
		filteredModel.setTable(keyTable);
		keyTable.getTableHeader().setReorderingAllowed(false);
		keyTable.getTableHeader().addMouseListener(new HeaderMouseHandler());
		keyTable.addMouseListener(new TableMouseHandler());
		Dimension d = keyTable.getPreferredSize();
		d.height = Math.min(d.height,200);
		JScrollPane scroller = new JScrollPane(keyTable);
		scroller.setPreferredSize(d);
		JPanel tableFilterPanel = new JPanel(new BorderLayout());
		tableFilterPanel.add(BorderLayout.NORTH,filterPanel);
		tableFilterPanel.add(BorderLayout.CENTER,scroller);

		add(BorderLayout.NORTH,north);
		add(BorderLayout.CENTER,tableFilterPanel);
		try
		{
			selectModel.setSelectedIndex(jEdit.getIntegerProperty("options.shortcuts.select.index", 0));
		}
		catch (IllegalArgumentException eae) {}
	} //}}}

	//{{{ _save() method
	@Override
	protected void _save()
	{
		if(keyTable.getCellEditor() != null)
			keyTable.getCellEditor().stopCellEditing();

		for (ShortcutsModel model : models)
			model.save();

		Macros.loadMacros();
	} //}}}

	//{{{ Private members
	private JTable keyTable;
	private Vector<ShortcutsModel> models;
	private FilteredTableModel<ShortcutsModel> filteredModel;
	private JComboBox selectModel;
	private List<KeyBinding> allBindings;
	private JTextField filterTF;

	//{{{ setFilter() method
	private void setFilter()
	{
		filteredModel.setFilter(filterTF.getText());
	} //}}}

	//{{{ initModels() method
	private void initModels()
	{
		List<KeyBinding[]> allBindings = new Vector<KeyBinding[]>();
		models = new Vector<ShortcutsModel>();
		ActionSet[] actionSets = jEdit.getActionSets();
		for(int i = 0; i < actionSets.length; i++)
		{
			ActionSet actionSet = actionSets[i];
			if(actionSet.getActionCount() != 0)
			{
				String modelLabel = actionSet.getLabel();
				if(modelLabel == null)
				{
					Log.log(Log.ERROR,this,"Empty action set: "
						+ actionSet.getPluginJAR());
				}
				ShortcutsModel model = createModel(modelLabel,
						actionSet.getActionNames());
				models.addElement(model);
				allBindings.addAll(model.getBindings());
			}
		}
		if (models.size() > 1)
			models.addElement(new ShortcutsModel("All", allBindings));
		Collections.sort(models,new StandardUtilities.StringCompare<ShortcutsModel>(true));
		ShortcutsModel currentModel = models.elementAt(0);
		filteredModel = new FilteredTableModel<ShortcutsModel>(currentModel)
		{
			@Override
			public String prepareFilter(String filter)
			{
				return filter.toLowerCase();
			}

			@Override
			public boolean passFilter(int row, String filter)
			{
				String name = delegated.getBindingAt(row, 0).label.toLowerCase();
				return name.contains(filter);
			}
		};
	} //}}}

	//{{{ createModel() method
	private ShortcutsModel createModel(String modelLabel, String[] actions)
	{
		List<GrabKeyDialog.KeyBinding[]> bindings = new Vector<GrabKeyDialog.KeyBinding[]>(actions.length);

		for(int i = 0; i < actions.length; i++)
		{
			String name = actions[i];
			EditAction ea = jEdit.getAction(name);
			String label = ea.getLabel();
			// Skip certain actions this way
			if(label == null)
				continue;

			label = GUIUtilities.prettifyMenuLabel(label);
			addBindings(name,label,bindings);
		}

		return new ShortcutsModel(modelLabel,bindings);
	} //}}}

	//{{{ addBindings() method
	private void addBindings(String name, String label, List<GrabKeyDialog.KeyBinding[]> bindings)
	{
		GrabKeyDialog.KeyBinding[] b = new GrabKeyDialog.KeyBinding[2];

		b[0] = createBinding(name,label,
			jEdit.getProperty(name + ".shortcut"));
		b[1] = createBinding(name,label,
			jEdit.getProperty(name + ".shortcut2"));

		bindings.add(b);
	} //}}}

	//{{{ createBinding() method
	private GrabKeyDialog.KeyBinding createBinding(String name,
		String label, String shortcut)
	{
		if(shortcut != null && shortcut.length() == 0)
			shortcut = null;

		GrabKeyDialog.KeyBinding binding
			= new GrabKeyDialog.KeyBinding(name,label,shortcut,false);

		allBindings.add(binding);
		return binding;
	} //}}}

	//{{{ Inner classes

	//{{{ HeaderMouseHandler class
	private class HeaderMouseHandler extends MouseAdapter
	{
		@Override
		public void mouseClicked(MouseEvent evt)
		{
			ShortcutsModel shortcutsModel = filteredModel.getDelegated();
			switch(keyTable.getTableHeader().columnAtPoint(evt.getPoint()))
			{
			case 0:
				shortcutsModel.sort(0);
				break;
			case 1:
				shortcutsModel.sort(1);
				break;
			case 2:
				shortcutsModel.sort(2);
				break;
			}
			setFilter();
		}
	} //}}}

	//{{{ TableMouseHandler class
	private class TableMouseHandler extends MouseAdapter
	{
		@Override
		public void mouseClicked(MouseEvent evt)
		{
			int row = keyTable.getSelectedRow();
			int col = keyTable.getSelectedColumn();
			if(col != 0 && row != -1)
			{
				 GrabKeyDialog gkd = new GrabKeyDialog(
					GUIUtilities.getParentDialog(
					ShortcutsOptionPane.this),
					filteredModel.getDelegated().getBindingAt(filteredModel.getTrueRow(row), col - 1),
					allBindings,null);
				if(gkd.isOK())
					filteredModel.setValueAt(
						gkd.getShortcut(),row,col);
			}
		}
	} //}}}

	//{{{ ActionHandler class
	private class ActionHandler implements ActionListener
	{
		public void actionPerformed(ActionEvent evt)
		{
			ShortcutsModel newModel
				= (ShortcutsModel)selectModel.getSelectedItem();
			if(filteredModel.getDelegated() != newModel)
			{
				jEdit.setIntegerProperty("options.shortcuts.select.index", selectModel.getSelectedIndex());
				filteredModel.setDelegated(newModel);
				setFilter();
			}
		}
	} //}}}

	//{{{ ShortcutsModel class
	private class ShortcutsModel extends AbstractTableModel
	{
		private List<GrabKeyDialog.KeyBinding[]> bindings;
		private String name;

		ShortcutsModel(String name, List<GrabKeyDialog.KeyBinding[]> bindings)
		{
			this.name = name;
			this.bindings = bindings;
			sort(0);
		}

		public List<GrabKeyDialog.KeyBinding[]> getBindings()
		{
			return bindings;
		}

		public void sort(int col)
		{
			Collections.sort(bindings,new KeyCompare(col));
		}

		public int getColumnCount()
		{
			return 3;
		}

		public int getRowCount()
		{
			return bindings.size();
		}

		public Object getValueAt(int row, int col)
		{
			switch(col)
			{
			case 0:
				return getBindingAt(row,0).label;
			case 1:
				return getBindingAt(row,0).shortcut;
			case 2:
				return getBindingAt(row,1).shortcut;
			default:
				return null;
			}
		}

		@Override
		public void setValueAt(Object value, int row, int col)
		{
			if(col == 0)
				return;

			getBindingAt(row,col-1).shortcut = (String)value;

			// redraw the whole table because a second shortcut
			// might have changed, too
			fireTableDataChanged();
		}

		@Override
		public String getColumnName(int index)
		{
			switch(index)
			{
			case 0:
				return jEdit.getProperty("options.shortcuts.name");
			case 1:
				return jEdit.getProperty("options.shortcuts.shortcut1");
			case 2:
				return jEdit.getProperty("options.shortcuts.shortcut2");
			default:
				return null;
			}
		}

		public void save()
		{
			for (GrabKeyDialog.KeyBinding[] binding : bindings)
			{
				jEdit.setProperty(
					binding[0].name + ".shortcut",
					binding[0].shortcut);
				jEdit.setProperty(
					binding[1].name + ".shortcut2",
					binding[1].shortcut);
			}
		}

		public GrabKeyDialog.KeyBinding getBindingAt(int row, int nr)
		{
			GrabKeyDialog.KeyBinding[] binding = bindings.get(row);
			return binding[nr];
		}

		@Override
		public String toString()
		{
			return name;
		}

		private class KeyCompare implements Comparator<GrabKeyDialog.KeyBinding[]>
		{
			private int col;

			KeyCompare(int col)
			{
				this.col = col;
			}

			public int compare(GrabKeyDialog.KeyBinding[] k1, GrabKeyDialog.KeyBinding[] k2)
			{
				String label1 = k1[0].label.toLowerCase();
				String label2 = k2[0].label.toLowerCase();

				if(col == 0)
					return StandardUtilities.compareStrings(
						label1,label2,true);
				else
				{
					String shortcut1, shortcut2;
					if(col == 1)
					{
						shortcut1 = k1[0].shortcut;
						shortcut2 = k2[0].shortcut;
					}
					else
					{
						shortcut1 = k1[1].shortcut;
						shortcut2 = k2[1].shortcut;
					}

					if(shortcut1 == null && shortcut2 != null)
						return 1;
					else if(shortcut2 == null && shortcut1 != null)
						return -1;
					else if(shortcut1 == null)
						return StandardUtilities.compareStrings(label1,label2,true);
					else
						return StandardUtilities.compareStrings(shortcut1,shortcut2,true);

FUNC_DECL TRY VAR_DECL VAR_DECL VAR_DECL VAR_DECL VAR_DECL VAR_DECL CATCH CALL CALL CALL CALL CALL ASSIGN CALL CALL CALL CALL ASSIGN CALL CALL CALL CALL CALL CALL ASSIGN CALL CALL CALL CALL CALL ASSIGN CALL CALL ASSIGN CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL LITERAL_ANCHOR CALL LITERAL_ANCHOR CALL CALL FUNC_DECL CALL CALL LITERAL_ANCHOR LITERAL_ANCHOR LITERAL_ANCHOR CALL LITERAL_ANCHOR LITERAL_ANCHOR LITERAL_ANCHOR LITERAL_ANCHOR LITERAL_ANCHOR LITERAL_ANCHOR PARAM LITERAL_ANCHOR FUNC_DECL FUNC_DECL FUNC_DECL LITERAL_ANCHOR CALL CALL PARAM PARAM PARAM LITERAL_ANCHOR CALL CALL CALL

FUNC_DECL LOOP IF CALL BINARY_OP CALL CALL LITERAL_ANCHOR CALL CALL


public final class WriterToUTF8Buffered extends Writer
{

  /** The byte stream to write to. (sc & sb remove final to compile in JDK 1.1.8) */
  private OutputStream m_os;

  /**
   * The internal buffer where data is stored.
   * (sc & sb remove final to compile in JDK 1.1.8)
   */
  private byte buf[];

  /**
   * The number of valid bytes in the buffer. This value is always
   * in the range <tt>0</tt> through <tt>buf.length</tt>; elements
   * <tt>buf[0]</tt> through <tt>buf[count-1]</tt> contain valid
   * byte data.
   */
  private int count;

  /**
   * Create an buffered UTF-8 writer.
   *
   *
   * @param   out    the underlying output stream.
   *
   * @throws UnsupportedEncodingException
   */
  public WriterToUTF8Buffered(OutputStream out)
          throws UnsupportedEncodingException
  {
    this(out, 8 * 1024);
  }

  /**
   * Create an buffered UTF-8 writer to write data to the
   * specified underlying output stream with the specified buffer
   * size.
   *
   * @param   out    the underlying output stream.
   * @param   size   the buffer size.
   * @exception IllegalArgumentException if size <= 0.
   */
  public WriterToUTF8Buffered(final OutputStream out, final int size)
  {

    m_os = out;

    if (size <= 0)
    {
    }

    buf = new byte[size];
    count = 0;
  }

  /**
   * Write a single character.  The character to be written is contained in
   * the 16 low-order bits of the given integer value; the 16 high-order bits
   * are ignored.
   *
   * <p> Subclasses that intend to support efficient single-character output
   * should override this method.
   *
   * @param c  int specifying a character to be written.
   * @exception  IOException  If an I/O error occurs
   */
  public void write(final int c) throws IOException
  {

    if (c < 0x80)
    {
      if (count >= buf.length)
        flushBuffer();
      buf[count++] = (byte) (c);
    }
    else if (c < 0x800)
    {
      if (count+1 >= buf.length)
        flushBuffer();
      buf[count++] = (byte) (0xc0 + (c >> 6));
      buf[count++] = (byte) (0x80 + (c & 0x3f));
    }
    else
    {
      if (count+2 >= buf.length)
        flushBuffer();
      buf[count++] = (byte) (0xe0 + (c >> 12));
      buf[count++] = (byte) (0x80 + ((c >> 6) & 0x3f));
      buf[count++] = (byte) (0x80 + (c & 0x3f));
    }
  }

  /**
   * Write a portion of an array of characters.
   *
   * @param  chars  Array of characters
   * @param  start   Offset from which to start writing characters
   * @param  length   Number of characters to write
   *
   * @exception  IOException  If an I/O error occurs
   *
   * @throws java.io.IOException
   */
  private final void writeDirect(
          final char chars[], final int start, final int length)
            throws java.io.IOException
  {

    final OutputStream os = m_os;

    int n = length+start;
    for (int i = start; i < n; i++)
    {
      final char c = chars[i];

      if (c < 0x80)
        os.write(c);
      else if (c < 0x800)
      {
        os.write(0xc0 + (c >> 6));
        os.write(0x80 + (c & 0x3f));
      }
      else
      {
        os.write(0xe0 + (c >> 12));
        os.write(0x80 + ((c >> 6) & 0x3f));
        os.write(0x80 + (c & 0x3f));
      }
    }
  }

  /**
   * Write a string.
   *
   * @param  s  String to be written
   *
   * @exception  IOException  If an I/O error occurs
   */
  private final void writeDirect(final String s) throws IOException
  {

    final int n = s.length();
    final OutputStream os = m_os;

    for (int i = 0; i < n; i++)
    {
      final char c = s.charAt(i);

      if (c < 0x80)
        os.write(c);
      else if (c < 0x800)
      {
        os.write(0xc0 + (c >> 6));
        os.write(0x80 + (c & 0x3f));
      }
      else
      {
        os.write(0xe0 + (c >> 12));
        os.write(0x80 + ((c >> 6) & 0x3f));
        os.write(0x80 + (c & 0x3f));
      }
    }
  }

  /**
   * Write a portion of an array of characters.
   *
   * @param  chars  Array of characters
   * @param  start   Offset from which to start writing characters
   * @param  length   Number of characters to write
   *
   * @exception  IOException  If an I/O error occurs
   *
   * @throws java.io.IOException
   */
  public void write(final char chars[], final int start, final int length)
          throws java.io.IOException
  {

    int lengthx3 = (length << 1) + length;

    if (lengthx3 >= buf.length)
    {

      /* If the request length exceeds the size of the output buffer,
         flush the output buffer and then write the data directly.
         In this way buffered streams will cascade harmlessly. */
      flushBuffer();
      writeDirect(chars, start, length);

      return;
    }

    if (lengthx3 > buf.length - count)
    {
      flushBuffer();
    }

    final OutputStream os = m_os;
    int n = length+start;
    for (int i = start; i < n; i++)
    {
      final char c = chars[i];

      if (c < 0x80)
        buf[count++] = (byte) (c);
      else if (c < 0x800)
      {
        buf[count++] = (byte) (0xc0 + (c >> 6));
        buf[count++] = (byte) (0x80 + (c & 0x3f));
      }
      else
      {
        buf[count++] = (byte) (0xe0 + (c >> 12));
        buf[count++] = (byte) (0x80 + ((c >> 6) & 0x3f));
        buf[count++] = (byte) (0x80 + (c & 0x3f));
      }
    }

  }

  /**
   * Write a string.
   *
   * @param  s  String to be written
   *
   * @exception  IOException  If an I/O error occurs
   */
  public void write(final String s) throws IOException
  {

    final int length = s.length();

    int lengthx3 = (length << 1) + length;

    if (lengthx3 >= buf.length)
    {

      /* If the request length exceeds the size of the output buffer,
         flush the output buffer and then write the data directly.
         In this way buffered streams will cascade harmlessly. */
      flushBuffer();
      writeDirect(s);

      return;
    }

    if (lengthx3 > buf.length - count)
    {
      flushBuffer();
    }

    final OutputStream os = m_os;

    for (int i = 0; i < length; i++)
    {
      final char c = s.charAt(i);

      if (c < 0x80)
        buf[count++] = (byte) (c);
      else if (c < 0x800)
      {
        buf[count++] = (byte) (0xc0 + (c >> 6));
        buf[count++] = (byte) (0x80 + (c & 0x3f));
      }
      else
      {
        buf[count++] = (byte) (0xe0 + (c >> 12));
        buf[count++] = (byte) (0x80 + ((c >> 6) & 0x3f));
        buf[count++] = (byte) (0x80 + (c & 0x3f));
      }
    }

  }

  /**
   * Flush the internal buffer
   *
   * @throws IOException
   */
  public void flushBuffer() throws IOException
  {

    if (count > 0)
    {
      m_os.write(buf, 0, count);

      count = 0;
    }
  }

  /**
   * Flush the stream.  If the stream has saved any characters from the
   * various write() methods in a buffer, write them immediately to their
   * intended destination.  Then, if that destination is another character or
   * byte stream, flush it.  Thus one flush() invocation will flush all the
   * buffers in a chain of Writers and OutputStreams.
   *
   * @exception  IOException  If an I/O error occurs
   *
   * @throws java.io.IOException
   */
  public void flush() throws java.io.IOException
  {
    flushBuffer();
    m_os.flush();
  }

  /**
   * Close the stream, flushing it first.  Once a stream has been closed,
   * further write() or flush() invocations will cause an IOException to be
   * thrown.  Closing a previously-closed stream, however, has no effect.
   *
   * @exception  IOException  If an I/O error occurs
   *
   * @throws java.io.IOException
   */
  public void close() throws java.io.IOException
  {
    flushBuffer();
    m_os.close();
  }

  /**
   * Get the output stream where the events will be serialized to.
   *
   * @return reference to the result stream, or null of only a writer was
   * set.
   */
  public OutputStream getOutputStream()
  {
    return m_os;


public class EmailAddress {
    private String name;
    private String address;

    /** Creates an empty email address  */
    public EmailAddress() {
    }

    /**
     * Creates a new email address based on the given string
     *
     * @param address the email address
     */
    public EmailAddress(String address) {
        this.address = address;
    }

    /**
     * Sets the personal / display name of the address
     *
     * @param name the display name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * Sets the email address
     *
     * @param address the actual email address
     */
    public void setAddress(String address) {
        this.address = address;
    }

    /**
     * Constructs a string "name <address>" or "address"
     *
     * @return a string representation of the address
     */
    public String toString() {
        if (name == null) {
            return address;
        } else {
            return name + " <" + address + ">";
        }
    }

    /**
     * Returns the address
     *
     * @return the address part
     */
    public String getAddress() {
        return address;
    }

    /**
     * Returns the display name
     *
     * @return the display name part
     */
    public String getName() {
        return name;

    public String getName() {
        return name;


public class TransformerFactoryImpl
    extends SAXTransformerFactory implements SourceLoader, ErrorListener
{
    public final static String TRANSLET_NAME = "translet-name";
    public final static String DESTINATION_DIRECTORY = "destination-directory";
    public final static String PACKAGE_NAME = "package-name";
    public final static String JAR_NAME = "jar-name";
    public final static String GENERATE_TRANSLET = "generate-translet";
    public final static String AUTO_TRANSLET = "auto-translet";
    public final static String USE_CLASSPATH = "use-classpath";
    public final static String DEBUG = "debug";
    public final static String ENABLE_INLINING = "enable-inlining";
    public final static String INDENT_NUMBER = "indent-number";

    /**
     * This error listener is used only for this factory and is not passed to
     * the Templates or Transformer objects that we create.
     */
    private ErrorListener _errorListener = this;

    /**
     * This URIResolver is passed to all created Templates and Transformers
     */
    private URIResolver _uriResolver = null;

    /**
     * As Gregor Samsa awoke one morning from uneasy dreams he found himself
     * transformed in his bed into a gigantic insect. He was lying on his hard,
     * as it were armour plated, back, and if he lifted his head a little he
     * could see his big, brown belly divided into stiff, arched segments, on
     * top of which the bed quilt could hardly keep in position and was about
     * to slide off completely. His numerous legs, which were pitifully thin
     * compared to the rest of his bulk, waved helplessly before his eyes.
     * "What has happened to me?", he thought. It was no dream....
     */
    protected final static String DEFAULT_TRANSLET_NAME = "GregorSamsa";

    /**
     * The class name of the translet
     */
    private String _transletName = DEFAULT_TRANSLET_NAME;

    /**
     * The destination directory for the translet
     */
    private String _destinationDirectory = null;

    /**
     * The package name prefix for all generated translet classes
     */
    private String _packageName = null;

    /**
     * The jar file name which the translet classes are packaged into
     */
    private String _jarFileName = null;

    /**
     * This Hashtable is used to store parameters for locating
     * <?xml-stylesheet ...?> processing instructions in XML docs.
     */
    private Hashtable _piParams = null;

    /**
     * The above hashtable stores objects of this class.
     */
    private static class PIParamWrapper {
	public String _media = null;
	public String _title = null;
	public String _charset = null;

	public PIParamWrapper(String media, String title, String charset) {
	    _media = media;
	    _title = title;
	    _charset = charset;
	}
    }

    /**
     * Set to true when debugging is enabled.
     */
    private boolean _debug = false;

    /**
     * Set to true when templates are inlined.
     */
    private boolean _enableInlining = false;

    /**
     * Set to true when we want to generate
     * translet classes from the stylesheet.
     */
    private boolean _generateTranslet = false;

    /**
     * If this is set to true, we attempt to use translet classes
     * for transformation if possible without compiling the stylesheet. The
     * translet class is only used if its timestamp is newer than the timestamp
     * of the stylesheet.
     */
    private boolean _autoTranslet = false;

    /**
     * If this is set to true, we attempt to load the translet
     * from the CLASSPATH.
     */
    private boolean _useClasspath = false;

    /**
     * Number of indent spaces when indentation is turned on.
     */
    private int _indentNumber = -1;

    /**
     * The provider of the XSLTC DTM Manager service.  This is fixed for any
     * instance of this class.  In order to change service providers, a new
     * XSLTC TransformerFactory must be instantiated.
     * @see XSLTCDTMManager#getDTMManagerClass()
     */
    private Class m_DTMManagerClass;

    /**
     *
State of secure processing feature.

     */
    private boolean _isSecureProcessing = false;

    /**
     * javax.xml.transform.sax.TransformerFactory implementation.
     */
    public TransformerFactoryImpl() {
        m_DTMManagerClass = XSLTCDTMManager.getDTMManagerClass();
    }

    /**
     * javax.xml.transform.sax.TransformerFactory implementation.
     * Set the error event listener for the TransformerFactory, which is used
     * for the processing of transformation instructions, and not for the
     * transformation itself.
     *
     * @param listener The error listener to use with the TransformerFactory
     * @throws IllegalArgumentException
     */
    public void setErrorListener(ErrorListener listener)
	throws IllegalArgumentException
    {
	if (listener == null) {
	    ErrorMsg err = new ErrorMsg(ErrorMsg.ERROR_LISTENER_NULL_ERR,
					"TransformerFactory");
            throw new IllegalArgumentException(err.toString());
	}
	_errorListener = listener;
    }

    /**
     * javax.xml.transform.sax.TransformerFactory implementation.
     * Get the error event handler for the TransformerFactory.
     *
     * @return The error listener used with the TransformerFactory
     */
    public ErrorListener getErrorListener() {
	return _errorListener;
    }

    /**
     * javax.xml.transform.sax.TransformerFactory implementation.
     * Returns the value set for a TransformerFactory attribute
     *
     * @param name The attribute name
     * @return An object representing the attribute value
     * @throws IllegalArgumentException
     */
    public Object getAttribute(String name)
	throws IllegalArgumentException
    {
	if (name.equals(TRANSLET_NAME)) {
	    return _transletName;
	}
	else if (name.equals(GENERATE_TRANSLET)) {
	    return new Boolean(_generateTranslet);
	}
	else if (name.equals(AUTO_TRANSLET)) {
	    return new Boolean(_autoTranslet);
	}

	ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_INVALID_ATTR_ERR, name);
	throw new IllegalArgumentException(err.toString());
    }

    /**
     * javax.xml.transform.sax.TransformerFactory implementation.
     * Sets the value for a TransformerFactory attribute.
     *
     * @param name The attribute name
     * @param value An object representing the attribute value
     * @throws IllegalArgumentException
     */
    public void setAttribute(String name, Object value)
	throws IllegalArgumentException
    {
	if (name.equals(TRANSLET_NAME) && value instanceof String) {
	    _transletName = (String) value;
	    return;
	}
	else if (name.equals(DESTINATION_DIRECTORY) && value instanceof String) {
	    _destinationDirectory = (String) value;
	    return;
	}
	else if (name.equals(PACKAGE_NAME) && value instanceof String) {
	    _packageName = (String) value;
	    return;
	}
	else if (name.equals(JAR_NAME) && value instanceof String) {
	    _jarFileName = (String) value;
	    return;
	}
	else if (name.equals(GENERATE_TRANSLET)) {
	    if (value instanceof Boolean) {
		_generateTranslet = ((Boolean) value).booleanValue();
		return;
	    }
	    else if (value instanceof String) {
		_generateTranslet = ((String) value).equalsIgnoreCase("true");
		return;
	    }
	}
	else if (name.equals(AUTO_TRANSLET)) {
	    if (value instanceof Boolean) {
		_autoTranslet = ((Boolean) value).booleanValue();
		return;
	    }
	    else if (value instanceof String) {
		_autoTranslet = ((String) value).equalsIgnoreCase("true");
		return;
	    }
	}
	else if (name.equals(USE_CLASSPATH)) {
	    if (value instanceof Boolean) {
		_useClasspath = ((Boolean) value).booleanValue();
		return;
	    }
	    else if (value instanceof String) {
		_useClasspath = ((String) value).equalsIgnoreCase("true");
		return;
	    }
	}
	else if (name.equals(DEBUG)) {
	    if (value instanceof Boolean) {
		_debug = ((Boolean) value).booleanValue();
		return;
	    }
	    else if (value instanceof String) {
		_debug = ((String) value).equalsIgnoreCase("true");
		return;
	    }
	}
	else if (name.equals(ENABLE_INLINING)) {
	    if (value instanceof Boolean) {
		_enableInlining = ((Boolean) value).booleanValue();
		return;
	    }
	    else if (value instanceof String) {
		_enableInlining = ((String) value).equalsIgnoreCase("true");
		return;
	    }
	}
	else if (name.equals(INDENT_NUMBER)) {
	    if (value instanceof String) {
		try {
		    _indentNumber = Integer.parseInt((String) value);
		    return;
		}
		catch (NumberFormatException e) {
		}
	    }
	    else if (value instanceof Integer) {
		_indentNumber = ((Integer) value).intValue();
		return;
	    }
	}

	final ErrorMsg err
	    = new ErrorMsg(ErrorMsg.JAXP_INVALID_ATTR_ERR, name);
	throw new IllegalArgumentException(err.toString());
    }

    /**
     *
Set a feature for this TransformerFactory and Transformers
     * or Templates created by this factory.

     *
     *

     * Feature names are fully qualified {@link java.net.URI}s.
     * Implementations may define their own features.
     * An {@link TransformerConfigurationException} is thrown if this TransformerFactory or the
     * Transformers or Templates it creates cannot support the feature.
     * It is possible for an TransformerFactory to expose a feature value but be unable to change its state.
     *

     *
     *
See {@link javax.xml.transform.TransformerFactory} for full documentation of specific features.

     *
     * @param name Feature name.
     * @param value Is feature state true or false.
     *
     * @throws TransformerConfigurationException if this TransformerFactory
     *   or the Transformers or Templates it creates cannot support this feature.
     * @throws NullPointerException If the name parameter is null.
     */
    public void setFeature(String name, boolean value)
        throws TransformerConfigurationException {

	if (name == null) {
            ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_SET_FEATURE_NULL_NAME);
    	    throw new NullPointerException(err.toString());
	}
	else if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) {
	    _isSecureProcessing = value;
	    return;
	}
	else {
            ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_UNSUPPORTED_FEATURE, name);
            throw new TransformerConfigurationException(err.toString());
        }
    }

    /**
     * javax.xml.transform.sax.TransformerFactory implementation.
     * Look up the value of a feature (to see if it is supported).
     * This method must be updated as the various methods and features of this
     * class are implemented.
     *
     * @param name The feature name
     * @return 'true' if feature is supported, 'false' if not
     */
    public boolean getFeature(String name) {
	String[] features = {
	    DOMSource.FEATURE,
	    DOMResult.FEATURE,
	    SAXSource.FEATURE,
	    SAXResult.FEATURE,
	    StreamSource.FEATURE,
	    StreamResult.FEATURE,
	    SAXTransformerFactory.FEATURE,
	    SAXTransformerFactory.FEATURE_XMLFILTER
	};

	if (name == null) {
    	    ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_GET_FEATURE_NULL_NAME);
    	    throw new NullPointerException(err.toString());
	}

	for (int i =0; i < features.length; i++) {
	    if (name.equals(features[i])) {
		return true;
	    }
	}
	if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) {
		return _isSecureProcessing;
	}

	return false;
    }

    /**
     * javax.xml.transform.sax.TransformerFactory implementation.
     * Get the object that is used by default during the transformation to
     * resolve URIs used in document(), xsl:import, or xsl:include.
     *
     * @return The URLResolver used for this TransformerFactory and all
     * Templates and Transformer objects created using this factory
     */
    public URIResolver getURIResolver() {
	return _uriResolver;
    }

    /**
     * javax.xml.transform.sax.TransformerFactory implementation.
     * Set the object that is used by default during the transformation to
     * resolve URIs used in document(), xsl:import, or xsl:include. Note that
     * this does not affect Templates and Transformers that are already
     * created with this factory.
     *
     * @param resolver The URLResolver used for this TransformerFactory and all
     * Templates and Transformer objects created using this factory
     */
    public void setURIResolver(URIResolver resolver) {
	_uriResolver = resolver;
    }

    /**
     * javax.xml.transform.sax.TransformerFactory implementation.
     * Get the stylesheet specification(s) associated via the xml-stylesheet
     * the document document specified in the source parameter, and that match
     * the given criteria.
     *
     * @param source The XML source document.
     * @param media The media attribute to be matched. May be null, in which
     * case the prefered templates will be used (i.e. alternate = no).
     * @param title The value of the title attribute to match. May be null.
     * @param charset The value of the charset attribute to match. May be null.
     * @return A Source object suitable for passing to the TransformerFactory.
     * @throws TransformerConfigurationException
     */
    public Source  getAssociatedStylesheet(Source source, String media,
					  String title, String charset)
	throws TransformerConfigurationException {

        String baseId;
        XMLReader reader = null;
        InputSource isource = null;

        /**
         * Fix for bugzilla bug 24187
         */
        StylesheetPIHandler _stylesheetPIHandler = new StylesheetPIHandler(null,media,title,charset);

        try {

            if (source instanceof DOMSource ) {
                final DOMSource domsrc = (DOMSource) source;
                baseId = domsrc.getSystemId();
                final org.w3c.dom.Node node = domsrc.getNode();
                final DOM2SAX dom2sax = new DOM2SAX(node);

                _stylesheetPIHandler.setBaseId(baseId);

                dom2sax.setContentHandler( _stylesheetPIHandler);
                dom2sax.parse();
            } else {
                isource = SAXSource.sourceToInputSource(source);
                baseId = isource.getSystemId();

                SAXParserFactory factory = SAXParserFactory.newInstance();
                factory.setNamespaceAware(true);

                if (_isSecureProcessing) {
                    try {
                        factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
                    }
                    catch (org.xml.sax.SAXException e) {}
                }

                SAXParser jaxpParser = factory.newSAXParser();

                reader = jaxpParser.getXMLReader();
                if (reader == null) {
                    reader = XMLReaderFactory.createXMLReader();
                }

                _stylesheetPIHandler.setBaseId(baseId);
                reader.setContentHandler(_stylesheetPIHandler);
                reader.parse(isource);

            }

            if (_uriResolver != null ) {
                _stylesheetPIHandler.setURIResolver(_uriResolver);
            }

        } catch (StopParseException e ) {

        } catch (javax.xml.parsers.ParserConfigurationException e) {

             throw new TransformerConfigurationException(
             "getAssociatedStylesheets failed", e);

        } catch (org.xml.sax.SAXException se) {

             throw new TransformerConfigurationException(
             "getAssociatedStylesheets failed", se);

        } catch (IOException ioe ) {
           throw new TransformerConfigurationException(
           "getAssociatedStylesheets failed", ioe);

        }

         return _stylesheetPIHandler.getAssociatedStylesheet();

    }

    /**
     * javax.xml.transform.sax.TransformerFactory implementation.
     * Create a Transformer object that copies the input document to the result.
     *
     * @return A Transformer object that simply copies the source to the result.
     * @throws TransformerConfigurationException
     */
    public Transformer newTransformer()
	throws TransformerConfigurationException
    {
	TransformerImpl result = new TransformerImpl(new Properties(),
	    _indentNumber, this);
	if (_uriResolver != null) {
	    result.setURIResolver(_uriResolver);
	}

	if (_isSecureProcessing) {
	    result.setSecureProcessing(true);
	}
	return result;
    }

    /**
     * javax.xml.transform.sax.TransformerFactory implementation.
     * Process the Source into a Templates object, which is a a compiled
     * representation of the source. Note that this method should not be
     * used with XSLTC, as the time-consuming compilation is done for each
     * and every transformation.
     *
     * @return A Templates object that can be used to create Transformers.
     * @throws TransformerConfigurationException
     */
    public Transformer newTransformer(Source source) throws
	TransformerConfigurationException
    {
	final Templates templates = newTemplates(source);
	final Transformer transformer = templates.newTransformer();
	if (_uriResolver != null) {
	    transformer.setURIResolver(_uriResolver);
	}
	return(transformer);
    }

    /**
     * Pass warning messages from the compiler to the error listener
     */
    private void passWarningsToListener(Vector messages)
	throws TransformerException
    {
	if (_errorListener == null || messages == null) {
	    return;
	}
	final int count = messages.size();
	for (int pos = 0; pos < count; pos++) {
	    ErrorMsg msg = (ErrorMsg)messages.elementAt(pos);
	    if (msg.isWarningError())
	        _errorListener.error(
		    new TransformerConfigurationException(msg.toString()));
	    else
	    	_errorListener.warning(
		    new TransformerConfigurationException(msg.toString()));
	}
    }

    /**
     * Pass error messages from the compiler to the error listener
     */
    private void passErrorsToListener(Vector messages) {
	try {
	    if (_errorListener == null || messages == null) {
		return;
	    }
	    final int count = messages.size();
	    for (int pos = 0; pos < count; pos++) {
		String message = messages.elementAt(pos).toString();
		_errorListener.error(new TransformerException(message));
	    }
	}
	catch (TransformerException e) {
	}
    }

    /**
     * javax.xml.transform.sax.TransformerFactory implementation.
     * Process the Source into a Templates object, which is a a compiled
     * representation of the source.
     *
     * @param source The input stylesheet - DOMSource not supported!!!
     * @return A Templates object that can be used to create Transformers.
     * @throws TransformerConfigurationException
     */
    public Templates newTemplates(Source source)
	throws TransformerConfigurationException
    {
	if (_useClasspath) {
	    String transletName = getTransletBaseName(source);

	    if (_packageName != null)
	        transletName = _packageName + "." + transletName;

	    try {
                final Class clazz = ObjectFactory.findProviderClass(
                    transletName, ObjectFactory.findClassLoader(), true);
	        resetTransientAttributes();

	        return new TemplatesImpl(new Class[]{clazz}, transletName, null, _indentNumber, this);
	    }
	    catch (ClassNotFoundException cnfe) {
	        ErrorMsg err = new ErrorMsg(ErrorMsg.CLASS_NOT_FOUND_ERR, transletName);
	        throw new TransformerConfigurationException(err.toString());
	    }
	    catch (Exception e) {
	        ErrorMsg err = new ErrorMsg(
                                     new ErrorMsg(ErrorMsg.RUNTIME_ERROR_KEY)
                                     + e.getMessage());
	        throw new TransformerConfigurationException(err.toString());
	    }
	}

	if (_autoTranslet)  {
	    byte[][] bytecodes = null;
	    String transletClassName = getTransletBaseName(source);

	    if (_packageName != null)
	        transletClassName = _packageName + "." + transletClassName;

	    if (_jarFileName != null)
	    	bytecodes = getBytecodesFromJar(source, transletClassName);
	    else
	    	bytecodes = getBytecodesFromClasses(source, transletClassName);

	    if (bytecodes != null) {
	    	if (_debug) {
	      	    if (_jarFileName != null)
	        	System.err.println(new ErrorMsg(
	            	    ErrorMsg.TRANSFORM_WITH_JAR_STR, transletClassName, _jarFileName));
	            else
	            	System.err.println(new ErrorMsg(
	            	    ErrorMsg.TRANSFORM_WITH_TRANSLET_STR, transletClassName));
	    	}

	    	resetTransientAttributes();

	    	return new TemplatesImpl(bytecodes, transletClassName, null, _indentNumber, this);
	    }
	}

	final XSLTC xsltc = new XSLTC();
	if (_debug) xsltc.setDebug(true);
	if (_enableInlining) xsltc.setTemplateInlining(true);
	if (_isSecureProcessing) xsltc.setSecureProcessing(true);
	xsltc.init();

	if (_uriResolver != null) {
	    xsltc.setSourceLoader(this);
	}

	if ((_piParams != null) && (_piParams.get(source) != null)) {
	    PIParamWrapper p = (PIParamWrapper)_piParams.get(source);
	    if (p != null) {
		xsltc.setPIParameters(p._media, p._title, p._charset);
	    }
	}

	int outputType = XSLTC.BYTEARRAY_OUTPUT;
	if (_generateTranslet || _autoTranslet) {
	    xsltc.setClassName(getTransletBaseName(source));

	    if (_destinationDirectory != null)
	    	xsltc.setDestDirectory(_destinationDirectory);
	    else {
	    	String xslName = getStylesheetFileName(source);
	    	if (xslName != null) {
	      	    File xslFile = new File(xslName);
	            String xslDir = xslFile.getParent();

	      	    if (xslDir != null)
	                xsltc.setDestDirectory(xslDir);
	    	}
	    }

	    if (_packageName != null)
	        xsltc.setPackageName(_packageName);

	    if (_jarFileName != null) {
	    	xsltc.setJarFileName(_jarFileName);
	    	outputType = XSLTC.BYTEARRAY_AND_JAR_OUTPUT;
	    }
	    else
	    	outputType = XSLTC.BYTEARRAY_AND_FILE_OUTPUT;
	}

	final InputSource input = Util.getInputSource(xsltc, source);
	byte[][] bytecodes = xsltc.compile(null, input, outputType);
	final String transletName = xsltc.getClassName();

	if ((_generateTranslet || _autoTranslet)
	   	&& bytecodes != null && _jarFileName != null) {
	    try {
	    	xsltc.outputToJar();
	    }
	    catch (java.io.IOException e) { }
	}

	resetTransientAttributes();

	if (_errorListener != this) {
	    try {
		passWarningsToListener(xsltc.getWarnings());
	    }
	    catch (TransformerException e) {
		throw new TransformerConfigurationException(e);
	    }
	}
	else {
	    xsltc.printWarnings();
	}

    if (bytecodes == null) {

        ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_COMPILE_ERR);
        TransformerConfigurationException exc =  new TransformerConfigurationException(err.toString());

        if (_errorListener != null) {
            passErrorsToListener(xsltc.getErrors());

            try {
                _errorListener.fatalError(exc);
            } catch (TransformerException te) {
            }
        }
        else {
            xsltc.printErrors();
        }
        throw exc;
    }

	return new TemplatesImpl(bytecodes, transletName,
	    xsltc.getOutputProperties(), _indentNumber, this);
    }

    /**
     * javax.xml.transform.sax.SAXTransformerFactory implementation.
     * Get a TemplatesHandler object that can process SAX ContentHandler
     * events into a Templates object.
     *
     * @return A TemplatesHandler object that can handle SAX events
     * @throws TransformerConfigurationException
     */
    public TemplatesHandler newTemplatesHandler()
	throws TransformerConfigurationException
    {
	final TemplatesHandlerImpl handler =
	    new TemplatesHandlerImpl(_indentNumber, this);
	if (_uriResolver != null) {
	    handler.setURIResolver(_uriResolver);
	}
	return handler;
    }

    /**
     * javax.xml.transform.sax.SAXTransformerFactory implementation.
     * Get a TransformerHandler object that can process SAX ContentHandler
     * events into a Result. This method will return a pure copy transformer.
     *
     * @return A TransformerHandler object that can handle SAX events
     * @throws TransformerConfigurationException
     */
    public TransformerHandler newTransformerHandler()
	throws TransformerConfigurationException
    {
	final Transformer transformer = newTransformer();
	if (_uriResolver != null) {
	    transformer.setURIResolver(_uriResolver);
	}
	return new TransformerHandlerImpl((TransformerImpl) transformer);
    }

    /**
     * javax.xml.transform.sax.SAXTransformerFactory implementation.
     * Get a TransformerHandler object that can process SAX ContentHandler
     * events into a Result, based on the transformation instructions
     * specified by the argument.
     *
     * @param src The source of the transformation instructions.
     * @return A TransformerHandler object that can handle SAX events
     * @throws TransformerConfigurationException
     */
    public TransformerHandler newTransformerHandler(Source src)
	throws TransformerConfigurationException
    {
	final Transformer transformer = newTransformer(src);
	if (_uriResolver != null) {
	    transformer.setURIResolver(_uriResolver);
	}
	return new TransformerHandlerImpl((TransformerImpl) transformer);
    }

    /**
     * javax.xml.transform.sax.SAXTransformerFactory implementation.
     * Get a TransformerHandler object that can process SAX ContentHandler
     * events into a Result, based on the transformation instructions
     * specified by the argument.
     *
     * @param templates Represents a pre-processed stylesheet
     * @return A TransformerHandler object that can handle SAX events
     * @throws TransformerConfigurationException
     */
    public TransformerHandler newTransformerHandler(Templates templates)
	throws TransformerConfigurationException
    {
	final Transformer transformer = templates.newTransformer();
	final TransformerImpl internal = (TransformerImpl)transformer;
	return new TransformerHandlerImpl(internal);
    }

    /**
     * javax.xml.transform.sax.SAXTransformerFactory implementation.
     * Create an XMLFilter that uses the given source as the
     * transformation instructions.
     *
     * @param src The source of the transformation instructions.
     * @return An XMLFilter object, or null if this feature is not supported.
     * @throws TransformerConfigurationException
     */
    public XMLFilter newXMLFilter(Source src)
	throws TransformerConfigurationException
    {
	Templates templates = newTemplates(src);
	if (templates == null) return null;
	return newXMLFilter(templates);
    }

    /**
     * javax.xml.transform.sax.SAXTransformerFactory implementation.
     * Create an XMLFilter that uses the given source as the
     * transformation instructions.
     *
     * @param templates The source of the transformation instructions.
     * @return An XMLFilter object, or null if this feature is not supported.
     * @throws TransformerConfigurationException
     */
    public XMLFilter newXMLFilter(Templates templates)
	throws TransformerConfigurationException
    {
	try {
      	    return new org.apache.xalan.xsltc.trax.TrAXFilter(templates);
    	}
	catch (TransformerConfigurationException e1) {
      	    if (_errorListener != null) {
                try {
          	    _errorListener.fatalError(e1);
          	    return null;
        	}
		catch (TransformerException e2) {
          	    new TransformerConfigurationException(e2);
        	}
      	    }
      	    throw e1;
    	}
    }

    /**
     * Receive notification of a recoverable error.
     * The transformer must continue to provide normal parsing events after
     * invoking this method. It should still be possible for the application
     * to process the document through to the end.
     *
     * @param e The warning information encapsulated in a transformer
     * exception.
     * @throws TransformerException if the application chooses to discontinue
     * the transformation (always does in our case).
     */
    public void error(TransformerException e)
	throws TransformerException
    {
	Throwable wrapped = e.getException();
        if (wrapped != null) {
            System.err.println(new ErrorMsg(ErrorMsg.ERROR_PLUS_WRAPPED_MSG,
                                            e.getMessageAndLocation(),
                                            wrapped.getMessage()));
        } else {
            System.err.println(new ErrorMsg(ErrorMsg.ERROR_MSG,
                                            e.getMessageAndLocation()));
	}
	throw e;
    }

    /**
     * Receive notification of a non-recoverable error.
     * The application must assume that the transformation cannot continue
     * after the Transformer has invoked this method, and should continue
     * (if at all) only to collect addition error messages. In fact,
     * Transformers are free to stop reporting events once this method has
     * been invoked.
     *
     * @param e warning information encapsulated in a transformer
     * exception.
     * @throws TransformerException if the application chooses to discontinue
     * the transformation (always does in our case).
     */
    public void fatalError(TransformerException e)
	throws TransformerException
    {
	Throwable wrapped = e.getException();
        if (wrapped != null) {
            System.err.println(new ErrorMsg(ErrorMsg.FATAL_ERR_PLUS_WRAPPED_MSG,
                                            e.getMessageAndLocation(),
                                            wrapped.getMessage()));
        } else {
            System.err.println(new ErrorMsg(ErrorMsg.FATAL_ERR_MSG,
                                            e.getMessageAndLocation()));
        }
	throw e;
    }

    /**
     * Receive notification of a warning.
     * Transformers can use this method to report conditions that are not
     * errors or fatal errors. The default behaviour is to take no action.
     * After invoking this method, the Transformer must continue with the
     * transformation. It should still be possible for the application to
     * process the document through to the end.
     *
     * @param e The warning information encapsulated in a transformer
     * exception.
     * @throws TransformerException if the application chooses to discontinue
     * the transformation (never does in our case).
     */
    public void warning(TransformerException e)
	throws TransformerException
    {
	Throwable wrapped = e.getException();
	if (wrapped != null) {
            System.err.println(new ErrorMsg(ErrorMsg.WARNING_PLUS_WRAPPED_MSG,
                                            e.getMessageAndLocation(),
                                            wrapped.getMessage()));
	} else {
            System.err.println(new ErrorMsg(ErrorMsg.WARNING_MSG,
                                            e.getMessageAndLocation()));
        }
    }

    /**
     * This method implements XSLTC's SourceLoader interface. It is used to
     * glue a TrAX URIResolver to the XSLTC compiler's Input and Import classes.
     *
     * @param href The URI of the document to load
     * @param context The URI of the currently loaded document
     * @param xsltc The compiler that resuests the document
     * @return An InputSource with the loaded document
     */
    public InputSource loadSource(String href, String context, XSLTC xsltc) {
	try {
	    if (_uriResolver != null) {
		final Source source = _uriResolver.resolve(href, context);
		if (source != null) {
		    return Util.getInputSource(xsltc, source);
		}
	    }
	}
	catch (TransformerException e) {
	}
	return null;
    }

    /**
     * Reset the per-session attributes to their default values
     */
    private void resetTransientAttributes() {
	_transletName = DEFAULT_TRANSLET_NAME;
	_destinationDirectory = null;
	_packageName = null;
	_jarFileName = null;
    }

    /**
     * Load the translet classes from local .class files and return
     * the bytecode array.
     *
     * @param source The xsl source
     * @param fullClassName The full name of the translet
     * @return The bytecode array
     */
    private byte[][] getBytecodesFromClasses(Source source, String fullClassName)
    {
    	if (fullClassName == null)
    	    return null;

    	String xslFileName = getStylesheetFileName(source);
    	File xslFile = null;
    	if (xslFileName != null)
    	    xslFile = new File(xslFileName);

    	final String transletName;
    	int lastDotIndex = fullClassName.lastIndexOf('.');
    	if (lastDotIndex > 0)
    	    transletName = fullClassName.substring(lastDotIndex+1);
    	else
    	    transletName = fullClassName;

    	String transletPath = fullClassName.replace('.', '/');
    	if (_destinationDirectory != null) {
    	    transletPath = _destinationDirectory + "/" + transletPath + ".class";
    	}
    	else {
    	    if (xslFile != null && xslFile.getParent() != null)
    	    	transletPath = xslFile.getParent() + "/" + transletPath + ".class";
    	    else
    	    	transletPath = transletPath + ".class";
    	}

    	File transletFile = new File(transletPath);
    	if (!transletFile.exists())
    	    return null;

    	if (xslFile != null && xslFile.exists()) {
    	    long xslTimestamp = xslFile.lastModified();
    	    long transletTimestamp = transletFile.lastModified();
    	    if (transletTimestamp < xslTimestamp)
    	    	return null;
    	}

    	Vector bytecodes = new Vector();
    	int fileLength = (int)transletFile.length();
    	if (fileLength > 0) {
    	    FileInputStream input = null;
    	    try {
    	    	input = new FileInputStream(transletFile);
    	    }
    	    catch (FileNotFoundException e) {
    	    	return null;
    	    }

    	    byte[] bytes = new byte[fileLength];
    	    try {
	    	readFromInputStream(bytes, input, fileLength);
	    	input.close();
	    }
	    catch (IOException e) {
    	    	return null;
    	    }

    	    bytecodes.addElement(bytes);
    	}
    	else
    	    return null;

    	String transletParentDir = transletFile.getParent();
    	if (transletParentDir == null)
    	    transletParentDir = System.getProperty("user.dir");

    	File transletParentFile = new File(transletParentDir);

    	final String transletAuxPrefix = transletName + "$";
    	File[] auxfiles = transletParentFile.listFiles(new FilenameFilter() {
        	public boolean accept(File dir, String name)
    		{
    		    return (name.endsWith(".class") && name.startsWith(transletAuxPrefix));
    		}
    	      });

    	for (int i = 0; i < auxfiles.length; i++)
    	{
    	    File auxfile = auxfiles[i];
    	    int auxlength = (int)auxfile.length();
    	    if (auxlength > 0) {
    	    	FileInputStream auxinput = null;
    	    	try {
    	      	    auxinput = new FileInputStream(auxfile);
    	    	}
    	    	catch (FileNotFoundException e) {
    	      	    continue;
    	    	}

    	    	byte[] bytes = new byte[auxlength];

    	    	try {
    	      	    readFromInputStream(bytes, auxinput, auxlength);
    	      	    auxinput.close();
    	    	}
    	    	catch (IOException e) {
    	      	    continue;
    	    	}

    	    	bytecodes.addElement(bytes);
    	    }
    	}

    	final int count = bytecodes.size();
    	if ( count > 0) {
    	    final byte[][] result = new byte[count][1];
    	    for (int i = 0; i < count; i++) {
    	    	result[i] = (byte[])bytecodes.elementAt(i);
    	    }

    	    return result;
    	}
    	else
    	    return null;
    }

    /**
     * Load the translet classes from the jar file and return the bytecode.
     *
     * @param source The xsl source
     * @param fullClassName The full name of the translet
     * @return The bytecode array
     */
    private byte[][] getBytecodesFromJar(Source source, String fullClassName)
    {
    	String xslFileName = getStylesheetFileName(source);
    	File xslFile = null;
    	if (xslFileName != null)
    	    xslFile = new File(xslFileName);

      	String jarPath = null;
      	if (_destinationDirectory != null)
            jarPath = _destinationDirectory + "/" + _jarFileName;
      	else {
      	    if (xslFile != null && xslFile.getParent() != null)
    	    	jarPath = xslFile.getParent() + "/" + _jarFileName;
    	    else
    	    	jarPath = _jarFileName;
    	}

      	File file = new File(jarPath);
      	if (!file.exists())
            return null;

    	if (xslFile != null && xslFile.exists()) {
    	    long xslTimestamp = xslFile.lastModified();
    	    long transletTimestamp = file.lastModified();
    	    if (transletTimestamp < xslTimestamp)
    	        return null;
    	}

      	ZipFile jarFile = null;
      	try {
            jarFile = new ZipFile(file);
      	}
      	catch (IOException e) {
            return null;
      	}

      	String transletPath = fullClassName.replace('.', '/');
      	String transletAuxPrefix = transletPath + "$";
      	String transletFullName = transletPath + ".class";

      	Vector bytecodes = new Vector();

      	Enumeration entries = jarFile.entries();
      	while (entries.hasMoreElements())
      	{
            ZipEntry entry = (ZipEntry)entries.nextElement();
            String entryName = entry.getName();
            if (entry.getSize() > 0 &&
            	  (entryName.equals(transletFullName) ||
              	  (entryName.endsWith(".class") &&
              	      entryName.startsWith(transletAuxPrefix))))
            {
            	try {
              	    InputStream input = jarFile.getInputStream(entry);
              	    int size = (int)entry.getSize();
              	    byte[] bytes = new byte[size];
              	    readFromInputStream(bytes, input, size);
              	    input.close();
              	    bytecodes.addElement(bytes);
            	}
            	catch (IOException e) {
              	    return null;
            	}
            }
      	}

    	final int count = bytecodes.size();
    	if (count > 0) {
    	    final byte[][] result = new byte[count][1];
    	    for (int i = 0; i < count; i++) {
    	    	result[i] = (byte[])bytecodes.elementAt(i);
    	    }

    	    return result;
    	}
    	else
    	    return null;
    }

    /**
     * Read a given number of bytes from the InputStream into a byte array.
     *
     * @param bytes The byte array to store the input content.
     * @param input The input stream.
     * @param size The number of bytes to read.
     */
    private void readFromInputStream(byte[] bytes, InputStream input, int size)
      	throws IOException
    {
      int n = 0;
      int offset = 0;
      int length = size;
      while (length > 0 && (n = input.read(bytes, offset, length)) > 0) {
          offset = offset + n;
          length = length - n;
      }
    }

    /**
     * Return the base class name of the translet.
     * The translet name is resolved using the following rules:
     * 1. if the _transletName attribute is set and its value is not "GregorSamsa",
     *    then _transletName is returned.
     * 2. otherwise get the translet name from the base name of the system ID
     * 3. return "GregorSamsa" if the result from step 2 is null.
     *
     * @param source The input Source
     * @return The name of the translet class
     */
    private String getTransletBaseName(Source source)
    {
        String transletBaseName = null;
        if (!_transletName.equals(DEFAULT_TRANSLET_NAME))
            return _transletName;
      	else {
            String systemId = source.getSystemId();
            if (systemId != null) {
          	String baseName = Util.baseName(systemId);
		if (baseName != null) {
		    baseName = Util.noExtName(baseName);
		    transletBaseName = Util.toJavaName(baseName);
		}
            }
      	}

        return (transletBaseName != null) ? transletBaseName : DEFAULT_TRANSLET_NAME;
    }

    /**
     *  Return the local file name from the systemId of the Source object
     *
     * @param source The Source
     * @return The file name in the local filesystem, or null if the
     * systemId does not represent a local file.
     */
    private String getStylesheetFileName(Source source)
    {
    	String systemId = source.getSystemId();
      	if (systemId != null) {
            File file = new File(systemId);
            if (file.exists())
                return systemId;
            else {
              	URL url = null;
          	try {
            	    url = new URL(systemId);
          	}
          	catch (MalformedURLException e) {
            	    return null;
          	}

          	if ("file".equals(url.getProtocol()))
            	    return url.getFile();
          	else
            	    return null;
            }
      	}
      	else
            return null;
    }

    /**
     * Returns the Class object the provides the XSLTC DTM Manager service.
     */
    protected Class getDTMManagerClass() {
        return m_DTMManagerClass;

FUNC_DECL THROW_RAISE VAR_DECL IF PARAM CALL IF CALL CALL CALL IF CALL RETURN CALL RETURN RETURN CALL CALL

FUNC_DECL THROW_RAISE VAR_DECL IF PARAM PARAM CALL IF BINARY_OP CALL CALL IF BINARY_OP RETURN BINARY_OP CALL IF BINARY_OP RETURN BINARY_OP CALL ASSIGN IF BINARY_OP RETURN BINARY_OP CALL ASSIGN IF CALL RETURN BINARY_OP CALL ASSIGN IF CALL IF ASSIGN IF CALL IF IF BINARY_OP IF CALL IF IF BINARY_OP BINARY_OP RETURN IF CALL IF IF BINARY_OP BINARY_OP RETURN RETURN ASSIGN CALL IF IF BINARY_OP BINARY_OP RETURN RETURN ASSIGN ASSIGN IF IF BINARY_OP BINARY_OP RETURN RETURN ASSIGN ASSIGN IF BINARY_OP BINARY_OP RETURN RETURN ASSIGN ASSIGN BINARY_OP TRY RETURN ASSIGN ASSIGN RETURN CATCH RETURN ASSIGN ASSIGN ASSIGN CALL

FUNC_DECL TRY PARAM CATCH RETURN THROW_RAISE IF CALL BINARY_OP TRY LITERAL_ANCHOR CATCH RETURN LITERAL_ANCHOR CALL CALL

FUNC_DECL THROW_RAISE IF VAR_DECL PARAM BINARY_OP LITERAL_ANCHOR CALL CALL CALL CALL CALL CALL CALL CALL

FUNC_DECL IF VAR_DECL PARAM BINARY_OP LITERAL_ANCHOR CALL CALL CALL CALL CALL CALL CALL CALL


@XmlType(name = "loadBalancerType")
@XmlAccessorType(XmlAccessType.FIELD)
public class LoadBalancerType extends IdentifiedType implements LoadBalancer {

    @XmlTransient
    private LoadBalancer loadBalancer;
    @XmlTransient
    private String loadBalancerTypeName;

    public LoadBalancerType() {
    }

    public LoadBalancerType(LoadBalancer loadBalancer) {
        this.loadBalancer = loadBalancer;
    }

    protected LoadBalancerType(String loadBalancerTypeName) {
        this.loadBalancerTypeName = loadBalancerTypeName;
    }

    public static LoadBalancer getLoadBalancer(RouteContext routeContext, LoadBalancerType type, String ref) {
        if (type == null) {
            notNull(ref, "ref or LoadBalancerType");
            LoadBalancer loadBalancer = routeContext.lookup(ref, LoadBalancer.class);
            if (loadBalancer instanceof LoadBalancerType) {
                type = (LoadBalancerType) loadBalancer;
            } else {
                return loadBalancer;
            }
        }
        return type.getLoadBalancer(routeContext);
    }

    /**
     * Sets a named property on the data format instance using introspection
     */
    protected void setProperty(Object bean, String name, Object value) {
        try {
            IntrospectionSupport.setProperty(bean, name, value);
        } catch (Exception e) {
            throw new IllegalArgumentException("Failed to set property " + name + " on " + bean
                                               + ". Reason: " + e, e);
        }
    }

    /**
     * Allows derived classes to customize the load balancer
     */
    protected void configureLoadBalancer(LoadBalancer loadBalancer) {
    }

    public LoadBalancer getLoadBalancer(RouteContext routeContext) {
        if (loadBalancer == null) {
            loadBalancer = createLoadBalancer(routeContext);
            ObjectHelper.notNull(loadBalancer, "loadBalancer");
            configureLoadBalancer(loadBalancer);
        }
        return loadBalancer;
    }

    /**
     * Factory method to create the load balancer instance
     */
    protected LoadBalancer createLoadBalancer(RouteContext routeContext) {
        if (loadBalancerTypeName != null) {
            Class type = ObjectHelper.loadClass(loadBalancerTypeName, getClass().getClassLoader());
            if (type == null) {
                throw new IllegalArgumentException("The class " + loadBalancerTypeName + " is not on the classpath! Cannot use the loadBalancer " + this);
            }
            return (LoadBalancer) ObjectHelper.newInstance(type);
        }
        return null;
    }

    public void addProcessor(Processor processor) {
        ObjectHelper.notNull(loadBalancer, "loadBalancer");
        loadBalancer.addProcessor(processor);
    }

    public List<Processor> getProcessors() {
        ObjectHelper.notNull(loadBalancer, "loadBalancer");
        return loadBalancer.getProcessors();
    }

    public void removeProcessor(Processor processor) {
        ObjectHelper.notNull(loadBalancer, "loadBalancer");
        loadBalancer.removeProcessor(processor);
    }

    public void process(Exchange exchange) throws Exception {
        ObjectHelper.notNull(loadBalancer, "loadBalancer");
        loadBalancer.process(exchange);
    }

    public boolean process(Exchange exchange, final AsyncCallback callback) {
        ObjectHelper.notNull(loadBalancer, "loadBalancer");

        return loadBalancer.process(exchange, new AsyncCallback() {
            public void done(boolean doneSynchronously) {
                if (doneSynchronously) {
                    return;
                } else {
                    callback.done(doneSynchronously);

FUNC_DECL RETURN PARAM PARAM CALL CALL CALL LITERAL_ANCHOR FUNC_DECL IF PARAM RETURN CALL


org.apache.poi.ddf.EscherProperty

abstract public class EscherProperty
{
    protected short  id;

    /**
     * The id is distinct from the actual property number.  The id includes the property number the blip id
     * flag and an indicator whether the property is complex or not.
     */
    public EscherProperty( short id )
    {
        this.id   = id;
    }

    /**
     * Constructs a new escher property.  The three parameters are combined to form a property
     * id.
     */
    public EscherProperty( short propertyNumber, boolean isComplex, boolean isBlipId )
    {
        this.id   = (short)(propertyNumber +
                (isComplex ? 0x8000 : 0x0) +
                (isBlipId ? 0x4000 : 0x0));
    }

    public short getId()
    {
        return id;
    }

    public short getPropertyNumber()
    {
        return (short) ( id & (short) 0x3FFF );
    }

    public boolean isComplex()
    {
        return ( id & (short) 0x8000 ) != 0;
    }

    public boolean isBlipId()
    {
        return ( id & (short) 0x4000 ) != 0;
    }

    public String getName()
    {
        return EscherProperties.getPropertyName(id);
    }

    /**
     * Most properties are just 6 bytes in length.  Override this if we're
     * dealing with complex properties.
     */
    public int getPropertySize()
    {
        return 6;
    }

    /**
     * Escher properties consist of a simple fixed length part and a complex variable length part.
     * The fixed length part is serialized first.
     */
    abstract public int serializeSimplePart( byte[] data, int pos );
    /**
     * Escher properties consist of a simple fixed length part and a complex variable length part.
     * The fixed length part is serialized first.
     */
    abstract public int serializeComplexPart( byte[] data, int pos );

    public short getId()
    {
        return id;


public class SizeSelector extends BaseExtendSelector {

    /** Constants for kilo, kibi etc */
    private static final int  KILO = 1000;
    private static final int  KIBI = 1024;
    private static final int  KIBI_POS = 4;
    private static final int  MEGA = 1000000;
    private static final int  MEGA_POS = 9;
    private static final int  MEBI = 1048576;
    private static final int  MEBI_POS = 13;
    private static final long GIGA = 1000000000L;
    private static final int  GIGA_POS = 18;
    private static final long GIBI = 1073741824L;
    private static final int  GIBI_POS = 22;
    private static final long TERA = 1000000000000L;
    private static final int  TERA_POS = 27;
    private static final long TEBI = 1099511627776L;
    private static final int  TEBI_POS = 31;
    private static final int  END_POS = 36;

    /** Used for parameterized custom selector */
    public static final String SIZE_KEY = "value";
    /** Used for parameterized custom selector */
    public static final String UNITS_KEY = "units";
    /** Used for parameterized custom selector */
    public static final String WHEN_KEY = "when";

    private long size = -1;
    private long multiplier = 1;
    private long sizelimit = -1;
    private Comparison when = Comparison.EQUAL;

    /**
     * Creates a new SizeSelector instance.
     *
     */
    public SizeSelector() {
    }

    /**
     * Returns a String object representing the specified
     * SizeSelector. This is "{sizeselector value: " + <"compare",
     * "less", "more", "equal"> + "}".
     * @return a string describing this object
     */
    public String toString() {
        StringBuffer buf = new StringBuffer("{sizeselector value: ");
        buf.append(sizelimit);
        buf.append("compare: ").append(when.getValue());
        buf.append("}");
        return buf.toString();
    }

    /**
     * A size selector needs to know what size to base its selecting on.
     * This will be further modified by the multiplier to get an
     * actual size limit.
     *
     * @param size the size to select against expressed in units.
     */
    public void setValue(long size) {
        this.size = size;
        if (multiplier != 0 && size > -1) {
            sizelimit = size * multiplier;
        }
    }

    /**
     * Sets the units to use for the comparison. This is a little
     * complicated because common usage has created standards that
     * play havoc with capitalization rules. Thus, some people will
     * use "K" for indicating 1000's, when the SI standard calls for
     * "k". Others have tried to introduce "K" as a multiple of 1024,
     * but that falls down when you reach "M", since "m" is already
     * defined as 0.001.
     *

     * To get around this complexity, a number of standards bodies
     * have proposed the 2^10 standard, and at least one has adopted
     * it. But we are still left with a populace that isn't clear on
     * how capitalization should work.
     *

     * We therefore ignore capitalization as much as possible.
     * Completely mixed case is not possible, but all upper and lower
     * forms are accepted for all long and short forms. Since we have
     * no need to work with the 0.001 case, this practice works here.
     *

     * This function translates all the long and short forms that a
     * unit prefix can occur in and translates them into a single
     * multiplier.
     *
     * @param units The units to compare the size to, using an
     *        EnumeratedAttribute.
     */
    public void setUnits(ByteUnits units) {
        int i = units.getIndex();
        multiplier = 0;
        if (i > -1 && i < KIBI_POS) {
            multiplier = KILO;
        } else if (i < MEGA_POS) {
            multiplier = KIBI;
        } else if (i < MEBI_POS) {
            multiplier = MEGA;
        } else if (i < GIGA_POS) {
            multiplier = MEBI;
        } else if (i < GIBI_POS) {
            multiplier = GIGA;
        } else if (i < TERA_POS) {
            multiplier = GIBI;
        } else if (i < TEBI_POS) {
            multiplier = TERA;
        } else if (i < END_POS) {
            multiplier = TEBI;
        }
        if (multiplier > 0 && size > -1) {
            sizelimit = size * multiplier;
        }
    }

    /**
     * This specifies when the file should be selected, whether it be
     * when the file matches a particular size, when it is smaller,
     * or whether it is larger.
     *
     * @param when The comparison to perform, an EnumeratedAttribute.
     */
    public void setWhen(SizeComparisons when) {
        this.when = when;
    }

    /**
     * When using this as a custom selector, this method will be called.
     * It translates each parameter into the appropriate setXXX() call.
     *
     * @param parameters the complete set of parameters for this selector.
     */
    public void setParameters(Parameter[] parameters) {
        super.setParameters(parameters);
        if (parameters != null) {
            for (int i = 0; i < parameters.length; i++) {
                String paramname = parameters[i].getName();
                if (SIZE_KEY.equalsIgnoreCase(paramname)) {
                    try {
                        setValue(Long.parseLong(parameters[i].getValue()));
                    } catch (NumberFormatException nfe) {
                        setError("Invalid size setting "
                                + parameters[i].getValue());
                    }
                } else if (UNITS_KEY.equalsIgnoreCase(paramname)) {
                    ByteUnits units = new ByteUnits();
                    units.setValue(parameters[i].getValue());
                    setUnits(units);
                } else if (WHEN_KEY.equalsIgnoreCase(paramname)) {
                    SizeComparisons scmp = new SizeComparisons();
                    scmp.setValue(parameters[i].getValue());
                    setWhen(scmp);
                } else {
                    setError("Invalid parameter " + paramname);
                }
            }
        }
    }

    /**
     *
Checks to make sure all settings are kosher. In this case, it
     * means that the size attribute has been set (to a positive value),
     * that the multiplier has a valid setting, and that the size limit
     * is valid. Since the latter is a calculated value, this can only
     * fail due to a programming error.
     *

     *
If a problem is detected, the setError() method is called.
     *

     */
    public void verifySettings() {
        if (size < 0) {
            setError("The value attribute is required, and must be positive");
        } else if (multiplier < 1) {
            setError("Invalid Units supplied, must be K,Ki,M,Mi,G,Gi,T,or Ti");
        } else if (sizelimit < 0) {
            setError("Internal error: Code is not setting sizelimit correctly");
        }
    }

    /**
     * The heart of the matter. This is where the selector gets to decide
     * on the inclusion of a file in a particular fileset.
     *
     * @param basedir A java.io.File object for the base directory.
     * @param filename The name of the file to check.
     * @param file A File object for this filename.
     * @return whether the file should be selected or not.
     */
    public boolean isSelected(File basedir, String filename, File file) {

        validate();

        if (file.isDirectory()) {
            return true;
        }
        long diff = file.length() - sizelimit;
        return when.evaluate(diff == 0 ? 0 : (int) (diff / Math.abs(diff)));
    }

    /**
     * Enumerated attribute with the values for units.
     *

     * This treats the standard SI units as representing powers of ten,
     * as they should. If you want the powers of 2 that approximate
     * the SI units, use the first two characters followed by a
     * bi. So 1024 (2^10) becomes kibi,
     * 1048576 (2^20) becomes mebi, 1073741824 (2^30)
     * becomes gibi, and so on. The symbols are also
     * accepted, and these are the first letter capitalized followed
     * by an i. Ki, Mi,
     * Gi, and so on. Capitalization variations on these
     * are also accepted.
     *

     * This binary prefix system is approved by the IEC and appears on
     * its way for approval by other agencies, but it is not an SI
     * standard. It disambiguates things for us, though.
     */
    public static class ByteUnits extends EnumeratedAttribute {
        /**
         * @return the values as an array of strings
         */
        public String[] getValues() {
            return new String[]{"K", "k", "kilo", "KILO",
                                "Ki", "KI", "ki", "kibi", "KIBI",
                                "M", "m", "mega", "MEGA",
                                "Mi", "MI", "mi", "mebi", "MEBI",
                                "G", "g", "giga", "GIGA",
                                "Gi", "GI", "gi", "gibi", "GIBI",
                                "T", "t", "tera", "TERA",
           /* You wish! */      "Ti", "TI", "ti", "tebi", "TEBI"
            };
        }
    }

    /**
     * Enumerated attribute with the values for size comparison.
     */
    public static class SizeComparisons extends Comparison {

FUNC_DECL IF PARAM BINARY_OP LOOP LITERAL_ANCHOR BINARY_OP IF VAR_DECL IF CALL LITERAL_ANCHOR IF CALL TRY CALL VAR_DECL CATCH CALL VAR_DECL CALL CALL CALL CALL CALL CALL CALL CALL CALL BINARY_OP CALL CALL BINARY_OP LITERAL_ANCHOR CALL LITERAL_ANCHOR CALL CALL


public class JmsProviderMetadata {
    private Class<? extends TemporaryQueue> temporaryQueueType;
    private Class<? extends TemporaryTopic> temporaryTopicType;

    /**
     * Lazily loads the temporary queue type if one has not been explicitly configured
     * via calling the {@link #setTemporaryQueueType(Class)}
     */
    public Class<? extends TemporaryQueue> getTemporaryQueueType(JmsOperations template) {
        Class<? extends TemporaryQueue> answer = getTemporaryQueueType();
        if (answer == null) {
            loadTemporaryDestinationTypes(template);
            answer = getTemporaryQueueType();
        }
        return answer;
    }

    /**
     * Lazily loads the temporary topic type if one has not been explicitly configured
     * via calling the {@link #setTemporaryTopicType(Class)}
     */
    public Class<? extends TemporaryTopic> getTemporaryTopicType(JmsOperations template) {
        Class<? extends TemporaryTopic> answer = getTemporaryTopicType();
        if (answer == null) {
            loadTemporaryDestinationTypes(template);
            answer = getTemporaryTopicType();
        }
        return answer;
    }

    public Class<? extends TemporaryQueue> getTemporaryQueueType() {
        return temporaryQueueType;
    }

    public void setTemporaryQueueType(Class<? extends TemporaryQueue> temporaryQueueType) {
        this.temporaryQueueType = temporaryQueueType;
    }

    public Class<? extends TemporaryTopic> getTemporaryTopicType() {
        return temporaryTopicType;
    }

    public void setTemporaryTopicType(Class<? extends TemporaryTopic> temporaryTopicType) {
        this.temporaryTopicType = temporaryTopicType;
    }

    protected void loadTemporaryDestinationTypes(JmsOperations template) {
        if (template == null) {
            throw new IllegalArgumentException("No JmsTemplate supplied!");
        }
        template.execute(new SessionCallback() {
            public Object doInJms(Session session) throws JMSException {
                TemporaryQueue queue = session.createTemporaryQueue();
                setTemporaryQueueType(queue.getClass());

                TemporaryTopic topic = session.createTemporaryTopic();
                setTemporaryTopicType(topic.getClass());

                queue.delete();
                topic.delete();
                return null;