Viewing Issue Advanced Details

ID 0003863 Category [DMDirc] IRC Parser Severity minor
Reproducibility always Date Submitted 2010-03-07 14:04 Last Update 2010-03-07 19:16
Reporter Error Reporter Assigned To MD87 View Status public
Priority normal Status resolved Resolution fixed
Platform Fixed in Version Target Version 0.6.4
Product Version Product Build 0.6.3-25-ge0ddbe1
Summary 0003863: Exception in Processor. [Process001]: null — parser.irc.IRCParser.joinChannels(IRCParser.java:1552)
Description
java.lang.NullPointerException
com.dmdirc.parser.irc.IRCParser.joinChannels(IRCParser.java:1552)
com.dmdirc.parser.irc.IRCParser.joinChannel(IRCParser.java:1495)
com.dmdirc.parser.irc.Process001.process(Process001.java:74)
com.dmdirc.parser.irc.ProcessingManager.process(ProcessingManager.java:193)
com.dmdirc.parser.irc.IRCParser.processLine(IRCParser.java:1136)
com.dmdirc.parser.irc.IRCParser.run(IRCParser.java:882)
java.lang.Thread.run(Thread.java:619)
Needs unit test no
Upstream Bug URL

Relationships

Notes

A patchset (3) related to this change has been added to gerrit by Chris Smith

Add joinChannels method and repurpose updateURI()

Fixes issue 3582
Fixes issue 3641
Fixes issue 3863 (dev error)
Issue 3623
Issue 3600

Change-Id: Ia0b147cfe1af5d5d5d1eae34c82e50ce23578d10
Depends-On: I1dac30977798780148eb27b8279a56a86b3bf890
authorChris Smith <chris@dmdirc.com>2010-03-07 14:12:42 (GMT)
committer Gregory Holmes <greg@dmdirc.com>2010-03-07 19:15:36 (GMT)
commit5c89ed6898c8db4c9bd52942146831b2a885a1fe (patch) (side-by-side diff)
Add joinChannels method and repurpose updateURI()
Fixes issue 3582 Fixes issue 3641 Fixes issue 3863 (dev error) Issue 3623 Issue 3600 Change-Id: Ia0b147cfe1af5d5d5d1eae34c82e50ce23578d10 Depends-On: I1dac30977798780148eb27b8279a56a86b3bf890 Reviewed-on: http://gerrit.dmdirc.com/979 Automatic-Compile: Chris Smith <chris@dmdirc.com> Reviewed-by: Gregory Holmes <greg@dmdirc.com>
-rw-r--r--src/com/dmdirc/parser/common/ChannelJoinRequest.java78
-rw-r--r--src/com/dmdirc/parser/interfaces/Parser.java31
-rw-r--r--src/com/dmdirc/parser/irc/IRCParser.java74
-rw-r--r--src/com/dmdirc/parser/irc/Process001.java2
4 files changed, 132 insertions, 53 deletions
Click to Expand/Collapse
diff src/com/dmdirc/parser/common/ChannelJoinRequest.java
new file mode 100644
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2006-2010 Chris Smith, Shane Mc Cormack, Gregory Holmes
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.dmdirc.parser.common;
+
+/**
+ * Describes the information needed to try and join a channel.
+ *
+ * @author chris
+ * @since 0.6.4
+ */
+public class ChannelJoinRequest {
+
+ /** The name of the channel to join (required). */
+ private final String name;
+ /** The name of the password to use (optional). */
+ private final String password;
+
+ /**
+ * Creates a new ChannelJoinRequest for a password-less channel with
+ * the specified name.
+ *
+ * @param name The name of the channel to join
+ */
+ public ChannelJoinRequest(final String name) {
+ this(name, null);
+ }
+
+ /**
+ * Creates a new ChannelJoinRequest for a channel with the specified
+ * password.
+ *
+ * @param name The name of the channel to join
+ * @param password The password to use
+ */
+ public ChannelJoinRequest(final String name, final String password) {
+ this.name = name;
+ this.password = password;
+ }
+
+ /**
+ * Retrieves the name of the channel this request will try to join.
+ *
+ * @return The name of the channel in this request
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Retrieves the password which will be used to try to join the channel.
+ *
+ * @return The password to use, or null if none specified
+ */
+ public String getPassword() {
+ return password;
+ }
+
+}
Click to Expand/Collapse
diff src/com/dmdirc/parser/interfaces/Parser.java
@@ -24,6 +24,7 @@ package com.dmdirc.parser.interfaces;
import com.dmdirc.parser.common.IgnoreList;
import com.dmdirc.parser.common.CallbackManager;
+import com.dmdirc.parser.common.ChannelJoinRequest;
import com.dmdirc.parser.common.QueuePriority;
import java.net.URI;
@@ -63,6 +64,14 @@ public interface Parser extends Runnable {
void joinChannel(String channel, String key);
/**
+ * Joins the specified channels.
+ *
+ * @since 0.6.4
+ * @param channels The channels to be joined
+ */
+ void joinChannels(ChannelJoinRequest ... channels);
+
+ /**
* Retrieves a channel information object for the specified channel.
*
* @param channel Name of the channel to retrieve an information object for
@@ -187,24 +196,12 @@ public interface Parser extends Runnable {
boolean compareURI(final URI uri);
/**
- * Updates this parser with a new URI. The new URI should be fundamentally
- * the same as the one the parser connected to (to the extent that
- * {@link #compareURI(java.net.URI)} returns true), but it may contain
- * extra information (such as an additional list of channels to join).
- * This operation should be non-destructive; that is, if the URI provided
- * contains less information than a previous URI, the 'missing' information
- * should not be treated as an instruction to remove it.
- * <p>
- * For example, if the parser was originally constructed with a URI
- * <code>irc://irc.quakenet.org/chan1,chan2</code>, and this method was
- * subsequently called with an argument of
- * <code>irc://irc.quakenet.org/chan3</code>, the IRC parser should join
- * the channel "chan3" and would also remain in chan1 and chan2.
- *
- * @param uri The URI to update this parser with
- * @since 0.6.3
+ * Extracts any channels present in the specified URI.
+ *
+ * @param uri The URI to extract channels from
+ * @since 0.6.4
*/
- void updateURI(final URI uri);
+ Collection<? extends ChannelJoinRequest> extractChannels(final URI uri);
/**
* Retrieves the name of the server that this parser is connected to.
Click to Expand/Collapse
diff src/com/dmdirc/parser/irc/IRCParser.java
@@ -39,6 +39,7 @@ import com.dmdirc.parser.interfaces.callbacks.Post005Listener;
import com.dmdirc.parser.interfaces.callbacks.ServerErrorListener;
import com.dmdirc.parser.interfaces.callbacks.SocketCloseListener;
import com.dmdirc.parser.common.CallbackManager;
+import com.dmdirc.parser.common.ChannelJoinRequest;
import com.dmdirc.parser.common.QueuePriority;
import java.io.BufferedReader;
@@ -53,6 +54,7 @@ import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
@@ -357,11 +359,33 @@ public class IRCParser implements SecureParser, Runnable {
/** {@inheritDoc} */
@Override
- public void updateURI(final URI uri) {
- final String channels = new ServerInfo(uri).getChannels();
- if (channels != null) {
- joinChannel(channels, true);
+ public Collection<? extends ChannelJoinRequest> extractChannels(final URI uri) {
+ return extractChannels(new ServerInfo(uri).getChannels());
+ }
+
+ /**
+ * Extracts a set of channels and optional keys from the specified String.
+ * Channels are separated by commas, and keys are separated from their
+ * channels by a space.
+ *
+ * @since 0.6.4
+ * @param channels The string of channels to parse
+ * @return A corresponding collection of join request objects
+ */
+ protected Collection<? extends ChannelJoinRequest> extractChannels(final String channels) {
+ final List<ChannelJoinRequest> res = new ArrayList<ChannelJoinRequest>();
+
+ for (String channel : channels.split(",")) {
+ final String[] parts = channel.split(" ", 2);
+
+ if (parts.length == 2) {
+ res.add(new ChannelJoinRequest(parts[0], parts[1]));
+ } else {
+ res.add(new ChannelJoinRequest(parts[0]));
+ }
}
+
+ return res;
}
/** {@inheritDoc} */
@@ -1468,24 +1492,13 @@ public class IRCParser implements SecureParser, Runnable {
/** {@inheritDoc} */
@Override
public void joinChannel(final String channel) {
- joinChannel(channel, "", true);
- }
-
- /**
- * Join a Channel.
- *
- * @param sChannelName Name of channel to join
- * @param autoPrefix Automatically prepend the first channel prefix defined
- * in 005 if sChannelName is an invalid channel.
- */
- public void joinChannel(final String sChannelName, final boolean autoPrefix) {
- joinChannel(sChannelName, "", autoPrefix);
+ joinChannels(extractChannels(channel).toArray(new ChannelJoinRequest[0]));
}
/** {@inheritDoc} */
@Override
public void joinChannel(final String channel, final String key) {
- joinChannel(channel, key, true);
+ joinChannels(new ChannelJoinRequest(channel, key));
}
/**
@@ -1497,35 +1510,26 @@ public class IRCParser implements SecureParser, Runnable {
* @param key Key to use to try and join the channel (If a list is given
* then this key will be used for any channels that do not
* specify one themselves.
- * @param autoPrefix Automatically prepend the first channel prefix defined
- * in 005 to any of the channels passsed if they are
- * otherwise invalid channels.
*/
- public void joinChannel(final String channel, final String key, final boolean autoPrefix) {
- final String[] bits = channel.split(",");
-
+ @Override
+ public void joinChannels(final ChannelJoinRequest ... channels) {
// We store a map from key->channels to allow intelligent joining of
// channels using as few JOIN commands as needed.
final Map<String, StringBuffer> joinMap = new HashMap<String, StringBuffer>();
- for (String bit : bits) {
- // Find any key for this channel
- final String[] keybits = bit.split(" ", 2);
- final String channelName = keybits[0];
- final String thisKey = (keybits.length > 1) ? keybits[1] : key;
-
+ for (ChannelJoinRequest channel : channels) {
// Make sure we have a list to put stuff in.
- StringBuffer list = joinMap.get(thisKey);
+ StringBuffer list = joinMap.get(channel.getPassword());
if (list == null) {
list = new StringBuffer();
- joinMap.put(thisKey, list);
+ joinMap.put(channel.getPassword(), list);
}
// Add the channel to the list. If the name is invalid and
// autoprefix is off we will just skip this channel.
- if (channelName.length() > 0 && (isValidChannelName(channelName) || autoPrefix)) {
+ if (!channel.getName().isEmpty()) {
if (list.length() > 0) { list.append(","); }
- if (!isValidChannelName(channelName) && autoPrefix) {
+ if (!isValidChannelName(channel.getName())) {
if (h005Info.containsKey("CHANTYPES")) {
final String chantypes = h005Info.get("CHANTYPES");
if (chantypes.isEmpty()) {
@@ -1537,7 +1541,7 @@ public class IRCParser implements SecureParser, Runnable {
list.append('#');
}
}
- list.append(channelName);
+ list.append(channel.getName());
}
}
@@ -1545,7 +1549,7 @@ public class IRCParser implements SecureParser, Runnable {
final String thisKey = entrySet.getKey();
final String channelString = entrySet.getValue().toString();
if (!channelString.isEmpty()) {
- if (thisKey.isEmpty()) {
+ if (thisKey == null || thisKey.isEmpty()) {
sendString("JOIN " + channelString);
} else {
sendString("JOIN " + channelString + " " + thisKey);
Click to Expand/Collapse
diff src/com/dmdirc/parser/irc/Process001.java
@@ -71,7 +71,7 @@ public class Process001 extends IRCProcessor {
final String channels = myParser.server.getChannels();
if (channels != null) {
- myParser.joinChannel(channels, true);
+ myParser.joinChannel(channels);
}
}

Issue History

Date Modified Username Field Change
2010-03-07 14:04 Error Reporter New Issue
2010-03-07 14:04 Error Reporter Status new => assigned
2010-03-07 14:04 Error Reporter Assigned To => Dataforce
2010-03-07 14:31 MD87 Assigned To Dataforce => MD87
2010-03-07 14:31 Version Control Checkin
2010-03-07 14:31 Version Control Note Added: 0010176
2010-03-07 14:31 Version Control Status assigned => fix pending
2010-03-07 14:31 MD87 View Status private => public
2010-03-07 19:16 MD87 Checkin
2010-03-07 19:16 MD87 Note Added: 0010196
2010-03-07 19:16 MD87 Status fix pending => resolved
2010-03-07 19:16 MD87 Resolution open => fixed