CustomXMLEscapes.java

/*
 ** Module   : CustomXMLEscapes.java
 ** Abstract : Class used in XML serialization that handles custom escaping of reserved characters.
 **
 ** Copyright (c) 2024, Golden Code Development Corporation.
 **
 ** -#- -I- --Date-- ---------------------------------------Description----------------------------------------
 ** 001 RNC  20241115 First version.
 */

/*
 ** This program is free software: you can redistribute it and/or modify
 ** it under the terms of the GNU Affero General Public License as
 ** published by the Free Software Foundation, either version 3 of the
 ** License, or (at your option) any later version.
 **
 ** This program is distributed in the hope that it will be useful,
 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ** GNU Affero General Public License for more details.
 **
 ** You may find a copy of the GNU Affero GPL version 3 at the following
 ** location: https://www.gnu.org/licenses/agpl-3.0.en.html
 **
 ** Additional terms under GNU Affero GPL version 3 section 7:
 **
 **   Under Section 7 of the GNU Affero GPL version 3, the following additional
 **   terms apply to the works covered under the License.  These additional terms
 **   are non-permissive additional terms allowed under Section 7 of the GNU
 **   Affero GPL version 3 and may not be removed by you.
 **
 **   0. Attribution Requirement.
 **
 **     You must preserve all legal notices or author attributions in the covered
 **     work or Appropriate Legal Notices displayed by works containing the covered
 **     work.  You may not remove from the covered work any author or developer
 **     credit already included within the covered work.
 **
 **   1. No License To Use Trademarks.
 **
 **     This license does not grant any license or rights to use the trademarks
 **     Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
 **     of Golden Code Development Corporation. You are not authorized to use the
 **     name Golden Code, FWD, or the names of any author or contributor, for
 **     publicity purposes without written authorization.
 **
 **   2. No Misrepresentation of Affiliation.
 **
 **     You may not represent yourself as Golden Code Development Corporation or FWD.
 **
 **     You may not represent yourself for publicity purposes as associated with
 **     Golden Code Development Corporation, FWD, or any author or contributor to
 **     the covered work, without written authorization.
 **
 **   3. No Misrepresentation of Source or Origin.
 **
 **     You may not represent the covered work as solely your work.  All modified
 **     versions of the covered work must be marked in a reasonable way to make it
 **     clear that the modified work is not originating from Golden Code Development
 **     Corporation or FWD.  All modified versions must contain the notices of
 **     attribution required in this license.
 */

package com.goldencode.p2j.xml;

import java.io.*;

import org.codehaus.stax2.io.EscapingWriterFactory;


/**
 * Custom writer which escapes all XML special characters (>, <, &quot, ', &).
 */
public class CustomXMLEscapes
implements EscapingWriterFactory
{
   /**
    * Creates a custom {@link Writer} that escapes XML special characters (<, >, &quot, ', &).
    *
    * @param    writer
    *           The {@link Writer} to wrap with the escaping logic.
    * @param    encoding
    *           The character encoding to be used for the output. Currently not used.
    *
    * @return    a {@link Writer} that applies the custom escaping logic for XML special characters.
    */
   @Override
   public Writer createEscapingWriterFor(Writer writer, String encoding)
   {
      return new EscapingWriter(writer);
   }

   /**
    * Creates a custom {@link Writer} that escapes XML special characters (<, >, &quot, ', &).
    *
    * @param    outputStream
    *           The {@link OutputStream} to wrap with the escaping logic.
    * @param    encoding
    *           The character encoding to be used for the output.
    *
    * @return   a {@link Writer} that applies the custom escaping logic for XML special characters.
    * @throws   UnsupportedEncodingException
    *           if the specified encoding is not supported.
    */
   @Override
   public Writer createEscapingWriterFor(OutputStream outputStream, String encoding)
   throws UnsupportedEncodingException
   {
      return new EscapingWriter(new OutputStreamWriter(outputStream, encoding));
   }

   /**
    * The implementation for the custom XML writer.
    */
   private static class EscapingWriter
   extends Writer
   {
      /** The {@link Writer} to which data is written. */
      private final Writer writer;

      /**
       * Initialize this instance to write escaped characters.
       *
       * @param    writer
       *           The {@link Writer} to which output will be written.
       */
      public EscapingWriter(Writer writer)
      {
         this.writer = writer;
      }

      /**
       * Writes a single character, escaping any XML special characters.
       *
       * @param    c
       *           The character to write.
       *
       * @throws   IOException
       *           if an I/O error occurs during writing.
       */
      @Override
      public void write(int c)
      throws IOException
      {
         switch (c)
         {
            case '<':
            {
               writer.write("&lt;");
               break;
            }
            case '>':
            {
               writer.write("&gt;");
               break;
            }
            case '"':
            {
               writer.write("&quot;");
               break;
            }
            case '\'':
            {
               writer.write("&apos;");
               break;
            }
            case '&':
            {
               writer.write("&amp;");
               break;
            }
            default:
            {
               writer.write(c);
               break;
            }
         }
      }

      /**
       * Writes a portion of a character array, escaping any XML special characters.
       *
       * @param    cbuf
       *           The character array to write from.
       * @param    off
       *           The offset from which to start writing characters.
       * @param    len
       *           The number of characters to write from the array.
       *
       * @throws   IOException
       *           if an I/O error occurs during writing.
       */
      @Override
      public void write(char[] cbuf, int off, int len)
      throws IOException
      {
         for (int i = off; i < off + len; i++)
         {
            write(cbuf[i]);
         }
      }

      /**
       * Flushes the underlying {@link #writer}, ensuring that any buffered output
       * is written to the destination.
       *
       * @throws   IOException
       *           if an I/O error occurs during flushing.
       */
      @Override
      public void flush()
      throws IOException
      {
         writer.flush();
      }

      /**
       * Closes the underlying {@link #writer}, releasing any system resources associated with it.
       *
       * @throws   IOException
       *           if an I/O error occurs during flushing.
       */
      @Override
      public void close()
      throws IOException
      {
         writer.close();
      }
   }
}