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 == &new ArrayList(CallbackObject#1)
* this.myManager == manager
* init'ed(this.myManager)
* this.myParser == parser
* init'ed(this.myParser)
* this.specificData == &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, &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, &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 |