File Source: CallbackObjectSpecific.java

         /* 
    P/P   *  Method: com.dmdirc.parser.irc.callbacks.CallbackObjectSpecific__static_init
          */
     1  /*
     2   * Copyright (c) 2006-2009 Chris Smith, Shane Mc Cormack, Gregory Holmes
     3   *
     4   * Permission is hereby granted, free of charge, to any person obtaining a copy
     5   * of this software and associated documentation files (the "Software"), to deal
     6   * in the Software without restriction, including without limitation the rights
     7   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     8   * copies of the Software, and to permit persons to whom the Software is
     9   * furnished to do so, subject to the following conditions:
    10   *
    11   * The above copyright notice and this permission notice shall be included in
    12   * all copies or substantial portions of the Software.
    13   *
    14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    20   * SOFTWARE.
    21   */
    22  
    23  package com.dmdirc.parser.irc.callbacks;
    24  
    25  import java.util.Hashtable;
    26  
    27  import com.dmdirc.parser.irc.ChannelInfo;
    28  import com.dmdirc.parser.irc.ClientInfo;
    29  import com.dmdirc.parser.irc.IRCParser;
    30  import com.dmdirc.parser.irc.ParserError;
    31  import com.dmdirc.parser.irc.callbacks.interfaces.ICallbackInterface;
    32  import java.util.ArrayList;
    33  
    34  /**
    35   * CallbackObjectSpecific.
    36   * Superclass for all callback types that have a "specific" target.
    37   *
    38   * @author            Shane Mc Cormack
    39   */
    40  public class CallbackObjectSpecific extends CallbackObject {
    41  	
    42  	/** Hashtable for storing specific information for callback. */	
    43  	protected volatile Hashtable<ICallbackInterface, String> specificData = new Hashtable<ICallbackInterface, String>();
    44  	
    45  	/**
    46  	 * Create a new instance of the Callback Object.
    47  	 *
    48  	 * @param parser IRCParser That owns this callback
    49  	 * @param manager CallbackManager that is in charge of this callback
    50       * @param type The type of callback to use
    51       * @since 0.6.3m1
    52  	 */
    53  	public CallbackObjectSpecific(final IRCParser parser,
    54              final CallbackManager manager, final Class<? extends ICallbackInterface> type) {
                 /* 
    P/P           *  Method: void com.dmdirc.parser.irc.callbacks.CallbackObjectSpecific(IRCParser, CallbackManager, Class)
                  * 
                  *  Postconditions:
                  *    this.callbackInfo == &amp;new ArrayList(CallbackObject#1)
                  *    this.myManager == manager
                  *    init'ed(this.myManager)
                  *    this.myParser == parser
                  *    init'ed(this.myParser)
                  *    this.specificData == &amp;new Hashtable(CallbackObjectSpecific#1)
                  *    this.type == type
                  *    init'ed(this.type)
                  *    new ArrayList(CallbackObject#1) num objects == 1
                  *    new Hashtable(CallbackObjectSpecific#1) num objects == 1
                  */
    55          super(parser, manager, type);
    56      }
    57  	
    58  	/**
    59  	 * Used to check if a channel matches the specificData.
    60  	 * 
    61  	 * @param eMethod Object that is being called back to
    62  	 * @param cChannel ChannelInfo object for the channel to test
    63  	 * @return true if channel given matches the specifics for the method given
    64  	 */
    65  	protected boolean isValidChan(final ICallbackInterface eMethod, final ChannelInfo cChannel) {
        		 /* 
    P/P 		  *  Method: bool isValidChan(ICallbackInterface, ChannelInfo)
        		  * 
        		  *  Preconditions:
        		  *    this.specificData != null
        		  *    (soft) cChannel != null
        		  *    (soft) init'ed(this.myParser.stringConverter)
        		  *    (soft) this.myParser != null
        		  *    (soft) this.myParser.stringConverter.lowercase != null
        		  *    (soft) this.myParser.stringConverter.lowercase.length >= 1
        		  *    (soft) init'ed(this.myParser.stringConverter.lowercase[...])
        		  * 
        		  *  Postconditions:
        		  *    init'ed(return_value)
        		  *    this.myParser.stringConverter == One-of{old this.myParser.stringConverter, &amp;new IRCStringConverter(getIRCStringConverter#1)}
        		  *    init'ed(this.myParser.stringConverter)
        		  *    new IRCStringConverter(getIRCStringConverter#1) num objects == 0
        		  *    not_init'ed(new IRCStringConverter(getIRCStringConverter#1).limit)
        		  *    not_init'ed(new IRCStringConverter(getIRCStringConverter#1).lowercase)
        		  *    not_init'ed(new IRCStringConverter(getIRCStringConverter#1).uppercase)
        		  *    new char[](IRCStringConverter#1) num objects == 0
        		  *    not_init'ed(new char[](IRCStringConverter#1).length)
        		  *    possibly_updated(new char[](IRCStringConverter#1)[...])
        		  *    ...
        		  * 
        		  *  Test Vectors:
        		  *    java.util.Hashtable:containsKey(...)@66: {0}, {1}
        		  */
    66  		if (specificData.containsKey(eMethod)) { 
    67  			if (!myParser.getIRCStringConverter().equalsIgnoreCase(cChannel.getName(), specificData.get(eMethod))) { return false; }
    68  		}
    69  		return true;
    70  	}
    71  	
    72  	/**
    73  	 * Used to check if a hostname matches the specificData.
    74  	 * 
    75  	 * @param eMethod Object that is being called back to
    76  	 * @param sHost Hostname of user that sent the query
    77  	 * @return true if host given matches the specifics for the method given
    78  	 */
    79  	protected boolean isValidUser(final ICallbackInterface eMethod, final String sHost) {
        		 /* 
    P/P 		  *  Method: bool isValidUser(ICallbackInterface, String)
        		  * 
        		  *  Preconditions:
        		  *    sHost != null
        		  *    this.specificData != null
        		  *    (soft) init'ed(this.myParser.stringConverter)
        		  *    (soft) this.myParser != null
        		  *    (soft) this.myParser.stringConverter.lowercase != null
        		  *    (soft) this.myParser.stringConverter.lowercase.length >= 1
        		  *    (soft) init'ed(this.myParser.stringConverter.lowercase[...])
        		  * 
        		  *  Postconditions:
        		  *    init'ed(return_value)
        		  *    this.myParser.stringConverter == One-of{old this.myParser.stringConverter, &amp;new IRCStringConverter(getIRCStringConverter#1)}
        		  *    init'ed(this.myParser.stringConverter)
        		  *    new IRCStringConverter(getIRCStringConverter#1) num objects == 0
        		  *    not_init'ed(new IRCStringConverter(getIRCStringConverter#1).limit)
        		  *    not_init'ed(new IRCStringConverter(getIRCStringConverter#1).lowercase)
        		  *    not_init'ed(new IRCStringConverter(getIRCStringConverter#1).uppercase)
        		  *    new char[](IRCStringConverter#1) num objects == 0
        		  *    not_init'ed(new char[](IRCStringConverter#1).length)
        		  *    possibly_updated(new char[](IRCStringConverter#1)[...])
        		  *    ...
        		  * 
        		  *  Test Vectors:
        		  *    java.util.Hashtable:containsKey(...)@81: {0}, {1}
        		  */
    80  		final String nickname = ClientInfo.parseHost(sHost);
    81  		if (specificData.containsKey(eMethod)) {
    82  			if (!myParser.getIRCStringConverter().equalsIgnoreCase(nickname, specificData.get(eMethod))) { return false; }
    83  		}
    84  		return true;
    85  	}
    86  	
    87  	// We override the default add method to make sure that any add with no
    88  	// specifics will have the specific data removed.
    89  	/**
    90  	 * Add a new callback.
    91  	 *
    92  	 * @param eMethod Object to callback to.
    93  	 */
    94      @Override
    95  	public void add(final ICallbackInterface eMethod) {
        		 /* 
    P/P 		  *  Method: void add(ICallbackInterface)
        		  * 
        		  *  Preconditions:
        		  *    this.callbackInfo != null
        		  *    this.specificData != null
        		  * 
        		  *  Test Vectors:
        		  *    java.util.Hashtable:containsKey(...)@97: {0}, {1}
        		  */
    96  		addCallback(eMethod);
    97  		if (specificData.containsKey(eMethod)) { specificData.remove(eMethod); }
    98  	}
    99  	
   100  	/**
   101  	 * Add a new callback with a specific target.
   102  	 *
   103  	 * @param eMethod Object to callback to.
   104  	 * @param specificTarget Target that must match for callback to be called.
   105  	 */
   106  	public void add(final ICallbackInterface eMethod, final String specificTarget) {
        		 /* 
    P/P 		  *  Method: void add(ICallbackInterface, String)
        		  * 
        		  *  Preconditions:
        		  *    specificTarget != null
        		  *    this.callbackInfo != null
        		  *    this.specificData != null
        		  * 
        		  *  Test Vectors:
        		  *    java.lang.String:isEmpty(...)@108: {1}, {0}
        		  */
   107  		add(eMethod);
   108  		if (!specificTarget.isEmpty()) {
   109  			specificData.put(eMethod, specificTarget);
   110  		}
   111  	}
   112  	
   113  	/**
   114  	 * Remove a callback.
   115  	 *
   116  	 * @param eMethod Object to remove callback to.
   117  	 */
   118      @Override
   119  	public void del(final ICallbackInterface eMethod) {
        		 /* 
    P/P 		  *  Method: void del(ICallbackInterface)
        		  * 
        		  *  Preconditions:
        		  *    this.callbackInfo != null
        		  *    this.specificData != null
        		  * 
        		  *  Test Vectors:
        		  *    java.util.Hashtable:containsKey(...)@121: {0}, {1}
        		  */
   120  		delCallback(eMethod);
   121  		if (specificData.containsKey(eMethod)) { specificData.remove(eMethod); }
   122  	}
   123  
   124      /**
   125       * Actually calls this callback. The specified arguments must match those
   126       * specified in the callback's interface, or an error will be raised.
   127       *
   128       * @param args The arguments to pass to the callback implementation
   129       * @return True if a method was called, false otherwise
   130       */
   131      @Override
   132      public boolean call(final Object ... args) {
        		 /* 
    P/P 		  *  Method: bool call(Object[])
        		  * 
        		  *  Preconditions:
        		  *    args != null
        		  *    this.myParser != null
        		  *    init'ed(this.myParser.createFake)
        		  *    (soft) args.length in {1..232}
        		  *    (soft) init'ed(args[0])
        		  *    (soft) args[0].sHost != null
        		  *    (soft) init'ed(args[...])
        		  *    (soft) args[...].sHost != null
        		  *    (soft) init'ed(this.myParser.stringConverter)
        		  *    (soft) this.myManager != null
        		  *    ...
        		  * 
        		  *  Presumptions:
        		  *    java.lang.Class:getMethods(...).length@156 >= 1
        		  *    java.lang.Class:getMethods(...)@156 != null
        		  *    java.lang.Class:getMethods(...)[0]@156 != null
        		  *    java.util.ArrayList:iterator(...)@143 != null
        		  *    this.myParser.stringConverter.lowercase.length@140 in range
        		  *    ...
        		  * 
        		  *  Postconditions:
        		  *    init'ed(return_value)
        		  *    init'ed(this.myParser.stringConverter)
        		  *    init'ed(new IRCStringConverter(getIRCStringConverter#1) num objects)
        		  *    init'ed(new IRCStringConverter(getIRCStringConverter#1).limit)
        		  *    init'ed(new IRCStringConverter(getIRCStringConverter#1).lowercase)
        		  *    init'ed(new IRCStringConverter(getIRCStringConverter#1).uppercase)
        		  *    init'ed(new char[](IRCStringConverter#1) num objects)
        		  *    init'ed(new char[](IRCStringConverter#1).length)
        		  *    init'ed(new char[](IRCStringConverter#1)[...])
        		  *    init'ed(new char[](IRCStringConverter#2) num objects)
        		  *    ...
        		  * 
        		  *  Test Vectors:
        		  *    this.myParser.createFake: {0}, {1}
        		  *    java.lang.Class:isAnnotationPresent(...)@144: {0}, {1}
        		  *    java.util.Iterator:hasNext(...)@143: {0}, {1}
        		  */
   133  		boolean bResult = false;
   134  
   135          final Object[] newArgs = new Object[args.length + 1];
   136          System.arraycopy(args, 0, newArgs, 1, args.length);
   137          newArgs[0] = myParser;
   138  
   139          if (myParser.getCreateFake()) {
   140              createFakeArgs(newArgs);
   141          }
   142  
   143  		for (ICallbackInterface iface :new ArrayList<ICallbackInterface>(callbackInfo)) {
   144              if (type.isAnnotationPresent(SpecificCallback.class) &&
   145                      ((args[0] instanceof ClientInfo
   146                          && !isValidUser(iface, ((ClientInfo) args[0]).getHost()))
   147                          || (args[0] instanceof ChannelInfo
   148                          && !isValidChan(iface, (ChannelInfo) args[0]))
   149                          || (!(args[0] instanceof ClientInfo || args[0] instanceof ChannelInfo) &&
   150                          args[args.length - 1] instanceof String
   151                          && !isValidUser(iface, (String) args[args.length - 1])))) {
   152                  continue;
   153              }
   154  
   155  			try {
   156                  type.getMethods()[0].invoke(iface, newArgs);
   157  			} catch (Exception e) {
   158  				final ParserError ei = new ParserError(ParserError.ERROR_ERROR,
   159                          "Exception in callback ("+e.getMessage()+")", myParser.getLastLine());
   160  				ei.setException(e);
   161  				callErrorInfo(ei);
   162  			}
   163  			bResult = true;
   164  		}
   165  		return bResult;
   166      }
   167  
   168  }








SofCheck Inspector Build Version : 2.17854
CallbackObjectSpecific.java 2009-Jun-25 01:54:24
CallbackObjectSpecific.class 2009-Sep-02 17:04:16