/*
 * jPOS Project [http://jpos.org]
 * Copyright (C) 2000-2008 Alejandro P. Revilla
 *
 * 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 should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.jpos.util;

import java.util.Vector;

import org.jpos.core.Configurable;
import org.jpos.core.Configuration;
import org.jpos.core.ConfigurationException;
import org.jpos.iso.ISOException;
import org.jpos.iso.ISOField;
import org.jpos.iso.ISOMsg;
import org.jpos.iso.ISOUtil;

/**
 * Protects selected fields from LogEvents.
 *
 * ProtectedLogListener acts like a filter for Event logs,
 * it should be defined _before_ other standard LogListeners
 * such as SimpleLogListener or RotateLogListeners.<br>
 * i.e.
 * <pre>
 * <logger name="qsp">
 *   <log-listener class="org.jpos.util.SimpleLogListener"/>
 *   <log-listener class="org.jpos.util.ProtectedLogListener">
 *     <property name="protect" value="2 35 45 55" />
 *     <property name="wipe"    value="48" />
 *   </log-listener>
 *   <log-listener class="org.jpos.util.RotateLogListener">
 *     <property name="file" value="/tmp/qsp.log" />
 *     <property name="window" value="86400" />
 *     <property name="copies" value="5" />
 *     <property name="maxsize" value="1000000" />
 *   </log-listener>
 * </logger>
 * </pre>
 * 
 * Order is important. In the previous example SimpleLogListener
 * will dump unprotected LogEvents while RotateLogListener will
 * dump protected ones (for selected fields)
 *
 * @author <a href="mailto:apr@cs.com.uy">Alejandro P. Revilla</a>
 * @version $Revision$ $Date$
 * @see org.jpos.core.Configurable
 * @since jPOS 1.3.3
 */
public class ProtectedLogListener implements LogListener, Configurable
{
    String[] protectFields = null;
    String[] wipeFields    = null;
    Configuration cfg   = null;

    public ProtectedLogListener () {
        super();
    }

   /**
    * Configure this ProtectedLogListener<br>
    * Properties:<br>
    * <ul>
    *  <li>[protect]   blank separated list of fields to be protected
    *  <li>[wipe]      blank separated list of fields to be wiped
    * </ul>
    * @param cfg Configuration 
    * @throws ConfigurationException
    */
    public void setConfiguration (Configuration cfg)
        throws ConfigurationException
    {
        this.cfg = cfg;
        protectFields = ISOUtil.toStringArray (cfg.get ("protect", ""));
        wipeFields    = ISOUtil.toStringArray (cfg.get ("wipe", ""));
    }
    public synchronized LogEvent log (LogEvent ev) {
        Vector payLoad = ev.getPayLoad();
        int size = payLoad.size();
        for (int i=0; i<size; i++) {
            Object obj = payLoad.elementAt (i);
            if (obj instanceof ISOMsg) {
                ISOMsg m = (ISOMsg) ((ISOMsg) obj).clone();
                try {
                    checkProtected (m);
                    checkHidden (m);
                } catch (ISOException e) { 
                    ev.addMessage (e);
                }
                payLoad.setElementAt (m, i);
            }
        }
        return ev;
    }
    private void checkProtected (ISOMsg m) throws ISOException {
        for (int i=0; i<protectFields.length; i++) {
            String f = protectFields[i];
            String v = m.getString(f);
            if (v != null) 
                m.set (f, ISOUtil.protect (v));
        }
    }
    private void checkHidden (ISOMsg m) throws ISOException {
        for (int i=0; i<wipeFields.length; i++) {
            String f = wipeFields[i];
            if (m.getValue(f) != null)
                m.set (f, "[WIPED]");
        }
    }
}

@@ -2365,16 +2365,143 @@
  = null;
+%0A    public static final String WIPED = %22%5BWIPED%5D%22;%0A    public static final byte%5B%5D BINARY_WIPED = ISOUtil.hex2byte (%22AA55AA55%22);
 %0A%0A    pu
@@ -3920,63 +3920,238 @@
     
-String v = m.getString(f);%0A            if (v != null) %0A
+Object v = null;%0A            try %7B%0A                v = m.getValue (f);%0A            %7D catch (ISOException e) %7B%0A                // ignore error%0A            %7D%0A            if (v != null) %7B%0A                if (v instanceof String)%0A    
     
@@ -4193,13 +4193,102 @@
 ct (
+(String) 
 v));%0A
+                else%0A                    m.set (f, BINARY_WIPED);%0A            %7D%0A
     
@@ -4461,20 +4461,71 @@
         
-if (
+Object v = null;%0A            try %7B%0A                v = 
 m.getVal
@@ -4526,19 +4526,124 @@
 getValue
+ 
 (f)
+;%0A            %7D catch (ISOException e) %7B%0A                // ignore error%0A            %7D%0A            if (v
  != null
@@ -4643,16 +4643,18 @@
 != null)
+ %7B
 %0A       
@@ -4666,29 +4666,150 @@
     
-m.set (f, %22%5BWIPED%5D%22);
+if (v instanceof String)%0A                    m.set (f, WIPED);%0A                else%0A                    m.set (f, BINARY_WIPED);%0A            %7D
 %0A   

deal with inner binary fields