Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Administrator
arthas-master
Commits
7c094a26
Commit
7c094a26
authored
Dec 18, 2023
by
liang.tang
Browse files
arthas-master
parents
Pipeline
#220
failed with stages
in 0 seconds
Changes
361
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
3360 additions
and
0 deletions
+3360
-0
client/src/main/java/org/apache/commons/net/telnet/TelnetClient.java
...main/java/org/apache/commons/net/telnet/TelnetClient.java
+414
-0
client/src/main/java/org/apache/commons/net/telnet/TelnetCommand.java
...ain/java/org/apache/commons/net/telnet/TelnetCommand.java
+131
-0
client/src/main/java/org/apache/commons/net/telnet/TelnetInputListener.java
...va/org/apache/commons/net/telnet/TelnetInputListener.java
+37
-0
client/src/main/java/org/apache/commons/net/telnet/TelnetInputStream.java
...java/org/apache/commons/net/telnet/TelnetInputStream.java
+680
-0
client/src/main/java/org/apache/commons/net/telnet/TelnetNotificationHandler.java
.../apache/commons/net/telnet/TelnetNotificationHandler.java
+68
-0
client/src/main/java/org/apache/commons/net/telnet/TelnetOption.java
...main/java/org/apache/commons/net/telnet/TelnetOption.java
+193
-0
client/src/main/java/org/apache/commons/net/telnet/TelnetOptionHandler.java
...va/org/apache/commons/net/telnet/TelnetOptionHandler.java
+283
-0
client/src/main/java/org/apache/commons/net/telnet/TelnetOutputStream.java
...ava/org/apache/commons/net/telnet/TelnetOutputStream.java
+165
-0
client/src/main/java/org/apache/commons/net/telnet/TerminalTypeOptionHandler.java
.../apache/commons/net/telnet/TerminalTypeOptionHandler.java
+112
-0
client/src/main/java/org/apache/commons/net/telnet/WindowSizeOptionHandler.java
...rg/apache/commons/net/telnet/WindowSizeOptionHandler.java
+162
-0
client/src/main/java/org/apache/commons/net/util/ListenerList.java
...c/main/java/org/apache/commons/net/util/ListenerList.java
+66
-0
common/pom.xml
common/pom.xml
+30
-0
common/src/main/java/com/taobao/arthas/common/AnsiLog.java
common/src/main/java/com/taobao/arthas/common/AnsiLog.java
+292
-0
common/src/main/java/com/taobao/arthas/common/ArthasConstants.java
...c/main/java/com/taobao/arthas/common/ArthasConstants.java
+41
-0
common/src/main/java/com/taobao/arthas/common/ExecutingCommand.java
.../main/java/com/taobao/arthas/common/ExecutingCommand.java
+110
-0
common/src/main/java/com/taobao/arthas/common/FileUtils.java
common/src/main/java/com/taobao/arthas/common/FileUtils.java
+150
-0
common/src/main/java/com/taobao/arthas/common/IOUtils.java
common/src/main/java/com/taobao/arthas/common/IOUtils.java
+165
-0
common/src/main/java/com/taobao/arthas/common/JavaVersionUtils.java
.../main/java/com/taobao/arthas/common/JavaVersionUtils.java
+61
-0
common/src/main/java/com/taobao/arthas/common/OSUtils.java
common/src/main/java/com/taobao/arthas/common/OSUtils.java
+136
-0
common/src/main/java/com/taobao/arthas/common/Pair.java
common/src/main/java/com/taobao/arthas/common/Pair.java
+64
-0
No files found.
Too many changes to show.
To preserve performance only
361 of 361+
files are displayed.
Plain diff
Email patch
client/src/main/java/org/apache/commons/net/telnet/TelnetClient.java
0 → 100644
View file @
7c094a26
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org.apache.commons.net.telnet
;
import
java.io.BufferedInputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.OutputStream
;
/***
* The TelnetClient class implements the simple network virtual
* terminal (NVT) for the Telnet protocol according to RFC 854. It
* does not implement any of the extra Telnet options because it
* is meant to be used within a Java program providing automated
* access to Telnet accessible resources.
* <p>
* The class can be used by first connecting to a server using the
* SocketClient
* {@link org.apache.commons.net.SocketClient#connect connect}
* method. Then an InputStream and OutputStream for sending and
* receiving data over the Telnet connection can be obtained by
* using the {@link #getInputStream getInputStream() } and
* {@link #getOutputStream getOutputStream() } methods.
* When you finish using the streams, you must call
* {@link #disconnect disconnect } rather than simply
* closing the streams.
***/
public
class
TelnetClient
extends
Telnet
{
private
InputStream
__input
;
private
OutputStream
__output
;
protected
boolean
readerThread
=
true
;
private
TelnetInputListener
inputListener
;
/***
* Default TelnetClient constructor, sets terminal-type {@code VT100}.
***/
public
TelnetClient
()
{
/* TERMINAL-TYPE option (start)*/
super
(
"VT100"
);
/* TERMINAL-TYPE option (end)*/
__input
=
null
;
__output
=
null
;
}
/**
* Construct an instance with the specified terminal type.
*
* @param termtype the terminal type to use, e.g. {@code VT100}
*/
/* TERMINAL-TYPE option (start)*/
public
TelnetClient
(
String
termtype
)
{
super
(
termtype
);
__input
=
null
;
__output
=
null
;
}
/* TERMINAL-TYPE option (end)*/
void
_flushOutputStream
()
throws
IOException
{
_output_
.
flush
();
}
void
_closeOutputStream
()
throws
IOException
{
_output_
.
close
();
}
/***
* Handles special connection requirements.
*
* @exception IOException If an error occurs during connection setup.
***/
@Override
protected
void
_connectAction_
()
throws
IOException
{
super
.
_connectAction_
();
TelnetInputStream
tmp
=
new
TelnetInputStream
(
_input_
,
this
,
readerThread
);
if
(
readerThread
)
{
tmp
.
_start
();
}
// __input CANNOT refer to the TelnetInputStream. We run into
// blocking problems when some classes use TelnetInputStream, so
// we wrap it with a BufferedInputStream which we know is safe.
// This blocking behavior requires further investigation, but right
// now it looks like classes like InputStreamReader are not implemented
// in a safe manner.
__input
=
new
BufferedInputStream
(
tmp
);
__output
=
new
TelnetOutputStream
(
this
);
}
/***
* Disconnects the telnet session, closing the input and output streams
* as well as the socket. If you have references to the
* input and output streams of the telnet connection, you should not
* close them yourself, but rather call disconnect to properly close
* the connection.
***/
@Override
public
void
disconnect
()
throws
IOException
{
if
(
__input
!=
null
)
{
__input
.
close
();
}
if
(
__output
!=
null
)
{
__output
.
close
();
}
super
.
disconnect
();
}
/***
* Returns the telnet connection output stream. You should not close the
* stream when you finish with it. Rather, you should call
* {@link #disconnect disconnect }.
*
* @return The telnet connection output stream.
***/
public
OutputStream
getOutputStream
()
{
return
__output
;
}
/***
* Returns the telnet connection input stream. You should not close the
* stream when you finish with it. Rather, you should call
* {@link #disconnect disconnect }.
*
* @return The telnet connection input stream.
***/
public
InputStream
getInputStream
()
{
return
__input
;
}
/***
* Returns the state of the option on the local side.
*
* @param option - Option to be checked.
*
* @return The state of the option on the local side.
***/
public
boolean
getLocalOptionState
(
int
option
)
{
/* BUG (option active when not already acknowledged) (start)*/
return
(
_stateIsWill
(
option
)
&&
_requestedWill
(
option
));
/* BUG (option active when not already acknowledged) (end)*/
}
/***
* Returns the state of the option on the remote side.
*
* @param option - Option to be checked.
*
* @return The state of the option on the remote side.
***/
public
boolean
getRemoteOptionState
(
int
option
)
{
/* BUG (option active when not already acknowledged) (start)*/
return
(
_stateIsDo
(
option
)
&&
_requestedDo
(
option
));
/* BUG (option active when not already acknowledged) (end)*/
}
/* open TelnetOptionHandler functionality (end)*/
/* Code Section added for supporting AYT (start)*/
/***
* Sends an Are You There sequence and waits for the result.
*
* @param timeout - Time to wait for a response (millis.)
*
* @return true if AYT received a response, false otherwise
*
* @throws InterruptedException on error
* @throws IllegalArgumentException on error
* @throws IOException on error
***/
public
boolean
sendAYT
(
long
timeout
)
throws
IOException
,
IllegalArgumentException
,
InterruptedException
{
return
(
_sendAYT
(
timeout
));
}
/* Code Section added for supporting AYT (start)*/
/***
* Sends a protocol-specific subnegotiation message to the remote peer.
* {@link TelnetClient} will add the IAC SB & IAC SE framing bytes;
* the first byte in {@code message} should be the appropriate telnet
* option code.
*
* <p>
* This method does not wait for any response. Subnegotiation messages
* sent by the remote end can be handled by registering an approrpriate
* {@link TelnetOptionHandler}.
* </p>
*
* @param message option code followed by subnegotiation payload
* @throws IllegalArgumentException if {@code message} has length zero
* @throws IOException if an I/O error occurs while writing the message
* @since 3.0
***/
public
void
sendSubnegotiation
(
int
[]
message
)
throws
IOException
,
IllegalArgumentException
{
if
(
message
.
length
<
1
)
{
throw
new
IllegalArgumentException
(
"zero length message"
);
}
_sendSubnegotiation
(
message
);
}
/***
* Sends a command byte to the remote peer, adding the IAC prefix.
*
* <p>
* This method does not wait for any response. Messages
* sent by the remote end can be handled by registering an approrpriate
* {@link TelnetOptionHandler}.
* </p>
*
* @param command the code for the command
* @throws IOException if an I/O error occurs while writing the message
* @throws IllegalArgumentException on error
* @since 3.0
***/
public
void
sendCommand
(
byte
command
)
throws
IOException
,
IllegalArgumentException
{
_sendCommand
(
command
);
}
/* open TelnetOptionHandler functionality (start)*/
/***
* Registers a new TelnetOptionHandler for this telnet client to use.
*
* @param opthand - option handler to be registered.
*
* @throws InvalidTelnetOptionException on error
* @throws IOException on error
***/
@Override
public
void
addOptionHandler
(
TelnetOptionHandler
opthand
)
throws
InvalidTelnetOptionException
,
IOException
{
super
.
addOptionHandler
(
opthand
);
}
/* open TelnetOptionHandler functionality (end)*/
/***
* Unregisters a TelnetOptionHandler.
*
* @param optcode - Code of the option to be unregistered.
*
* @throws InvalidTelnetOptionException on error
* @throws IOException on error
***/
@Override
public
void
deleteOptionHandler
(
int
optcode
)
throws
InvalidTelnetOptionException
,
IOException
{
super
.
deleteOptionHandler
(
optcode
);
}
/* Code Section added for supporting spystreams (start)*/
/***
* Registers an OutputStream for spying what's going on in
* the TelnetClient session.
*
* @param spystream - OutputStream on which session activity
* will be echoed.
***/
public
void
registerSpyStream
(
OutputStream
spystream
)
{
super
.
_registerSpyStream
(
spystream
);
}
/***
* Stops spying this TelnetClient.
*
***/
public
void
stopSpyStream
()
{
super
.
_stopSpyStream
();
}
/* Code Section added for supporting spystreams (end)*/
/***
* Registers a notification handler to which will be sent
* notifications of received telnet option negotiation commands.
*
* @param notifhand - TelnetNotificationHandler to be registered
***/
@Override
public
void
registerNotifHandler
(
TelnetNotificationHandler
notifhand
)
{
super
.
registerNotifHandler
(
notifhand
);
}
/***
* Unregisters the current notification handler.
*
***/
@Override
public
void
unregisterNotifHandler
()
{
super
.
unregisterNotifHandler
();
}
/***
* Sets the status of the reader thread.
*
* <p>
* When enabled, a seaparate internal reader thread is created for new
* connections to read incoming data as it arrives. This results in
* immediate handling of option negotiation, notifications, etc.
* (at least until the fixed-size internal buffer fills up).
* Otherwise, no thread is created an all negotiation and option
* handling is deferred until a read() is performed on the
* {@link #getInputStream input stream}.
* </p>
*
* <p>
* The reader thread must be enabled for {@link TelnetInputListener}
* support.
* </p>
*
* <p>
* When this method is invoked, the reader thread status will apply to all
* subsequent connections; the current connection (if any) is not affected.
* </p>
*
* @param flag true to enable the reader thread, false to disable
* @see #registerInputListener
***/
public
void
setReaderThread
(
boolean
flag
)
{
readerThread
=
flag
;
}
/***
* Gets the status of the reader thread.
*
* @return true if the reader thread is enabled, false otherwise
***/
public
boolean
getReaderThread
()
{
return
(
readerThread
);
}
/***
* Register a listener to be notified when new incoming data is
* available to be read on the {@link #getInputStream input stream}.
* Only one listener is supported at a time.
*
* <p>
* More precisely, notifications are issued whenever the number of
* bytes available for immediate reading (i.e., the value returned
* by {@link InputStream#available}) transitions from zero to non-zero.
* Note that (in general) multiple reads may be required to empty the
* buffer and reset this notification, because incoming bytes are being
* added to the internal buffer asynchronously.
* </p>
*
* <p>
* Notifications are only supported when a {@link #setReaderThread
* reader thread} is enabled for the connection.
* </p>
*
* @param listener listener to be registered; replaces any previous
* @since 3.0
***/
public
synchronized
void
registerInputListener
(
TelnetInputListener
listener
)
{
this
.
inputListener
=
listener
;
}
/***
* Unregisters the current {@link TelnetInputListener}, if any.
*
* @since 3.0
***/
public
synchronized
void
unregisterInputListener
()
{
this
.
inputListener
=
null
;
}
// Notify input listener
void
notifyInputListener
()
{
TelnetInputListener
listener
;
synchronized
(
this
)
{
listener
=
this
.
inputListener
;
}
if
(
listener
!=
null
)
{
listener
.
telnetInputAvailable
();
}
}
}
client/src/main/java/org/apache/commons/net/telnet/TelnetCommand.java
0 → 100644
View file @
7c094a26
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org.apache.commons.net.telnet
;
/**
* The TelnetCommand class cannot be instantiated and only serves as a
* storehouse for telnet command constants.
* @see org.apache.commons.net.telnet.Telnet
* @see org.apache.commons.net.telnet.TelnetClient
*/
public
final
class
TelnetCommand
{
/*** The maximum value a command code can have. This value is 255. ***/
public
static
final
int
MAX_COMMAND_VALUE
=
255
;
/*** Interpret As Command code. Value is 255 according to RFC 854. ***/
public
static
final
int
IAC
=
255
;
/*** Don't use option code. Value is 254 according to RFC 854. ***/
public
static
final
int
DONT
=
254
;
/*** Request to use option code. Value is 253 according to RFC 854. ***/
public
static
final
int
DO
=
253
;
/*** Refuse to use option code. Value is 252 according to RFC 854. ***/
public
static
final
int
WONT
=
252
;
/*** Agree to use option code. Value is 251 according to RFC 854. ***/
public
static
final
int
WILL
=
251
;
/*** Start subnegotiation code. Value is 250 according to RFC 854. ***/
public
static
final
int
SB
=
250
;
/*** Go Ahead code. Value is 249 according to RFC 854. ***/
public
static
final
int
GA
=
249
;
/*** Erase Line code. Value is 248 according to RFC 854. ***/
public
static
final
int
EL
=
248
;
/*** Erase Character code. Value is 247 according to RFC 854. ***/
public
static
final
int
EC
=
247
;
/*** Are You There code. Value is 246 according to RFC 854. ***/
public
static
final
int
AYT
=
246
;
/*** Abort Output code. Value is 245 according to RFC 854. ***/
public
static
final
int
AO
=
245
;
/*** Interrupt Process code. Value is 244 according to RFC 854. ***/
public
static
final
int
IP
=
244
;
/*** Break code. Value is 243 according to RFC 854. ***/
public
static
final
int
BREAK
=
243
;
/*** Data mark code. Value is 242 according to RFC 854. ***/
public
static
final
int
DM
=
242
;
/*** No Operation code. Value is 241 according to RFC 854. ***/
public
static
final
int
NOP
=
241
;
/*** End subnegotiation code. Value is 240 according to RFC 854. ***/
public
static
final
int
SE
=
240
;
/*** End of record code. Value is 239. ***/
public
static
final
int
EOR
=
239
;
/*** Abort code. Value is 238. ***/
public
static
final
int
ABORT
=
238
;
/*** Suspend process code. Value is 237. ***/
public
static
final
int
SUSP
=
237
;
/*** End of file code. Value is 236. ***/
public
static
final
int
EOF
=
236
;
/*** Synchronize code. Value is 242. ***/
public
static
final
int
SYNCH
=
242
;
/*** String representations of commands. ***/
private
static
final
String
__commandString
[]
=
{
"IAC"
,
"DONT"
,
"DO"
,
"WONT"
,
"WILL"
,
"SB"
,
"GA"
,
"EL"
,
"EC"
,
"AYT"
,
"AO"
,
"IP"
,
"BRK"
,
"DMARK"
,
"NOP"
,
"SE"
,
"EOR"
,
"ABORT"
,
"SUSP"
,
"EOF"
};
private
static
final
int
__FIRST_COMMAND
=
IAC
;
private
static
final
int
__LAST_COMMAND
=
EOF
;
/***
* Returns the string representation of the telnet protocol command
* corresponding to the given command code.
* <p>
* @param code The command code of the telnet protocol command.
* @return The string representation of the telnet protocol command.
***/
public
static
final
String
getCommand
(
int
code
)
{
return
__commandString
[
__FIRST_COMMAND
-
code
];
}
/***
* Determines if a given command code is valid. Returns true if valid,
* false if not.
* <p>
* @param code The command code to test.
* @return True if the command code is valid, false if not.
**/
public
static
final
boolean
isValidCommand
(
int
code
)
{
return
(
code
<=
__FIRST_COMMAND
&&
code
>=
__LAST_COMMAND
);
}
// Cannot be instantiated
private
TelnetCommand
()
{
}
}
client/src/main/java/org/apache/commons/net/telnet/TelnetInputListener.java
0 → 100644
View file @
7c094a26
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org.apache.commons.net.telnet
;
/***
* Listener interface used for notification that incoming data is
* available to be read.
*
* @see TelnetClient
* @since 3.0
***/
public
interface
TelnetInputListener
{
/***
* Callback method invoked when new incoming data is available on a
* {@link TelnetClient}'s {@link TelnetClient#getInputStream input stream}.
*
* @see TelnetClient#registerInputListener
***/
public
void
telnetInputAvailable
();
}
client/src/main/java/org/apache/commons/net/telnet/TelnetInputStream.java
0 → 100644
View file @
7c094a26
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org.apache.commons.net.telnet
;
import
java.io.BufferedInputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.InterruptedIOException
;
final
class
TelnetInputStream
extends
BufferedInputStream
implements
Runnable
{
/** End of file has been reached */
private
static
final
int
EOF
=
-
1
;
/** Read would block */
private
static
final
int
WOULD_BLOCK
=
-
2
;
// TODO should these be private enums?
static
final
int
_STATE_DATA
=
0
,
_STATE_IAC
=
1
,
_STATE_WILL
=
2
,
_STATE_WONT
=
3
,
_STATE_DO
=
4
,
_STATE_DONT
=
5
,
_STATE_SB
=
6
,
_STATE_SE
=
7
,
_STATE_CR
=
8
,
_STATE_IAC_SB
=
9
;
private
boolean
__hasReachedEOF
;
// @GuardedBy("__queue")
private
volatile
boolean
__isClosed
;
private
boolean
__readIsWaiting
;
private
int
__receiveState
,
__queueHead
,
__queueTail
,
__bytesAvailable
;
private
final
int
[]
__queue
;
private
final
TelnetClient
__client
;
private
final
Thread
__thread
;
private
IOException
__ioException
;
/* TERMINAL-TYPE option (start)*/
private
final
int
__suboption
[]
=
new
int
[
512
];
private
int
__suboption_count
=
0
;
/* TERMINAL-TYPE option (end)*/
private
volatile
boolean
__threaded
;
TelnetInputStream
(
InputStream
input
,
TelnetClient
client
,
boolean
readerThread
)
{
super
(
input
);
__client
=
client
;
__receiveState
=
_STATE_DATA
;
__isClosed
=
true
;
__hasReachedEOF
=
false
;
// Make it 2049, because when full, one slot will go unused, and we
// want a 2048 byte buffer just to have a round number (base 2 that is)
__queue
=
new
int
[
2049
];
__queueHead
=
0
;
__queueTail
=
0
;
__bytesAvailable
=
0
;
__ioException
=
null
;
__readIsWaiting
=
false
;
__threaded
=
false
;
if
(
readerThread
)
{
__thread
=
new
Thread
(
this
);
}
else
{
__thread
=
null
;
}
}
TelnetInputStream
(
InputStream
input
,
TelnetClient
client
)
{
this
(
input
,
client
,
true
);
}
void
_start
()
{
if
(
__thread
==
null
)
{
return
;
}
int
priority
;
__isClosed
=
false
;
// TODO remove this
// Need to set a higher priority in case JVM does not use pre-emptive
// threads. This should prevent scheduler induced deadlock (rather than
// deadlock caused by a bug in this code).
priority
=
Thread
.
currentThread
().
getPriority
()
+
1
;
if
(
priority
>
Thread
.
MAX_PRIORITY
)
{
priority
=
Thread
.
MAX_PRIORITY
;
}
__thread
.
setPriority
(
priority
);
__thread
.
setDaemon
(
true
);
__thread
.
start
();
__threaded
=
true
;
// tell _processChar that we are running threaded
}
// synchronized(__client) critical sections are to protect against
// TelnetOutputStream writing through the telnet client at same time
// as a processDo/Will/etc. command invoked from TelnetInputStream
// tries to write.
/**
* Get the next byte of data.
* IAC commands are processed internally and do not return data.
*
* @param mayBlock true if method is allowed to block
* @return the next byte of data,
* or -1 (EOF) if end of stread reached,
* or -2 (WOULD_BLOCK) if mayBlock is false and there is no data available
*/
private
int
__read
(
boolean
mayBlock
)
throws
IOException
{
int
ch
;
while
(
true
)
{
// If there is no more data AND we were told not to block,
// just return WOULD_BLOCK (-2). (More efficient than exception.)
if
(!
mayBlock
&&
super
.
available
()
==
0
)
{
return
WOULD_BLOCK
;
}
// Otherwise, exit only when we reach end of stream.
if
((
ch
=
super
.
read
())
<
0
)
{
return
EOF
;
}
ch
=
(
ch
&
0xff
);
/* Code Section added for supporting AYT (start)*/
synchronized
(
__client
)
{
__client
.
_processAYTResponse
();
}
/* Code Section added for supporting AYT (end)*/
/* Code Section added for supporting spystreams (start)*/
__client
.
_spyRead
(
ch
);
/* Code Section added for supporting spystreams (end)*/
switch
(
__receiveState
)
{
case
_STATE_CR:
if
(
ch
==
'\0'
)
{
// Strip null
continue
;
}
// How do we handle newline after cr?
// else if (ch == '\n' && _requestedDont(TelnetOption.ECHO) &&
// Handle as normal data by falling through to _STATE_DATA case
//$FALL-THROUGH$
case
_STATE_DATA:
if
(
ch
==
TelnetCommand
.
IAC
)
{
__receiveState
=
_STATE_IAC
;
continue
;
}
if
(
ch
==
'\r'
)
{
synchronized
(
__client
)
{
if
(
__client
.
_requestedDont
(
TelnetOption
.
BINARY
))
{
__receiveState
=
_STATE_CR
;
}
else
{
__receiveState
=
_STATE_DATA
;
}
}
}
else
{
__receiveState
=
_STATE_DATA
;
}
break
;
case
_STATE_IAC:
switch
(
ch
)
{
case
TelnetCommand
.
WILL
:
__receiveState
=
_STATE_WILL
;
continue
;
case
TelnetCommand
.
WONT
:
__receiveState
=
_STATE_WONT
;
continue
;
case
TelnetCommand
.
DO
:
__receiveState
=
_STATE_DO
;
continue
;
case
TelnetCommand
.
DONT
:
__receiveState
=
_STATE_DONT
;
continue
;
/* TERMINAL-TYPE option (start)*/
case
TelnetCommand
.
SB
:
__suboption_count
=
0
;
__receiveState
=
_STATE_SB
;
continue
;
/* TERMINAL-TYPE option (end)*/
case
TelnetCommand
.
IAC
:
__receiveState
=
_STATE_DATA
;
break
;
// exit to enclosing switch to return IAC from read
case
TelnetCommand
.
SE
:
// unexpected byte! ignore it (don't send it as a command)
__receiveState
=
_STATE_DATA
;
continue
;
default
:
__receiveState
=
_STATE_DATA
;
__client
.
_processCommand
(
ch
);
// Notify the user
continue
;
// move on the next char
}
break
;
// exit and return from read
case
_STATE_WILL:
synchronized
(
__client
)
{
__client
.
_processWill
(
ch
);
__client
.
_flushOutputStream
();
}
__receiveState
=
_STATE_DATA
;
continue
;
case
_STATE_WONT:
synchronized
(
__client
)
{
__client
.
_processWont
(
ch
);
__client
.
_flushOutputStream
();
}
__receiveState
=
_STATE_DATA
;
continue
;
case
_STATE_DO:
synchronized
(
__client
)
{
__client
.
_processDo
(
ch
);
__client
.
_flushOutputStream
();
}
__receiveState
=
_STATE_DATA
;
continue
;
case
_STATE_DONT:
synchronized
(
__client
)
{
__client
.
_processDont
(
ch
);
__client
.
_flushOutputStream
();
}
__receiveState
=
_STATE_DATA
;
continue
;
/* TERMINAL-TYPE option (start)*/
case
_STATE_SB:
switch
(
ch
)
{
case
TelnetCommand
.
IAC
:
__receiveState
=
_STATE_IAC_SB
;
continue
;
default
:
// store suboption char
if
(
__suboption_count
<
__suboption
.
length
)
{
__suboption
[
__suboption_count
++]
=
ch
;
}
break
;
}
__receiveState
=
_STATE_SB
;
continue
;
case
_STATE_IAC_SB:
// IAC received during SB phase
switch
(
ch
)
{
case
TelnetCommand
.
SE
:
synchronized
(
__client
)
{
__client
.
_processSuboption
(
__suboption
,
__suboption_count
);
__client
.
_flushOutputStream
();
}
__receiveState
=
_STATE_DATA
;
continue
;
case
TelnetCommand
.
IAC
:
// De-dup the duplicated IAC
if
(
__suboption_count
<
__suboption
.
length
)
{
__suboption
[
__suboption_count
++]
=
ch
;
}
break
;
default
:
// unexpected byte! ignore it
break
;
}
__receiveState
=
_STATE_SB
;
continue
;
/* TERMINAL-TYPE option (end)*/
}
break
;
}
return
ch
;
}
// synchronized(__client) critical sections are to protect against
// TelnetOutputStream writing through the telnet client at same time
// as a processDo/Will/etc. command invoked from TelnetInputStream
// tries to write. Returns true if buffer was previously empty.
private
boolean
__processChar
(
int
ch
)
throws
InterruptedException
{
// Critical section because we're altering __bytesAvailable,
// __queueTail, and the contents of _queue.
boolean
bufferWasEmpty
;
synchronized
(
__queue
)
{
bufferWasEmpty
=
(
__bytesAvailable
==
0
);
while
(
__bytesAvailable
>=
__queue
.
length
-
1
)
{
// The queue is full. We need to wait before adding any more data to it. Hopefully the stream owner
// will consume some data soon!
if
(
__threaded
)
{
__queue
.
notify
();
try
{
__queue
.
wait
();
}
catch
(
InterruptedException
e
)
{
throw
e
;
}
}
else
{
// We've been asked to add another character to the queue, but it is already full and there's
// no other thread to drain it. This should not have happened!
throw
new
IllegalStateException
(
"Queue is full! Cannot process another character."
);
}
}
// Need to do this in case we're not full, but block on a read
if
(
__readIsWaiting
&&
__threaded
)
{
__queue
.
notify
();
}
__queue
[
__queueTail
]
=
ch
;
++
__bytesAvailable
;
if
(++
__queueTail
>=
__queue
.
length
)
{
__queueTail
=
0
;
}
}
return
bufferWasEmpty
;
}
@Override
public
int
read
()
throws
IOException
{
// Critical section because we're altering __bytesAvailable,
// __queueHead, and the contents of _queue in addition to
// testing value of __hasReachedEOF.
synchronized
(
__queue
)
{
while
(
true
)
{
if
(
__ioException
!=
null
)
{
IOException
e
;
e
=
__ioException
;
__ioException
=
null
;
throw
e
;
}
if
(
__bytesAvailable
==
0
)
{
// Return EOF if at end of file
if
(
__hasReachedEOF
)
{
return
EOF
;
}
// Otherwise, we have to wait for queue to get something
if
(
__threaded
)
{
__queue
.
notify
();
try
{
__readIsWaiting
=
true
;
__queue
.
wait
();
__readIsWaiting
=
false
;
}
catch
(
InterruptedException
e
)
{
throw
new
InterruptedIOException
(
"Fatal thread interruption during read."
);
}
}
else
{
//__alreadyread = false;
__readIsWaiting
=
true
;
int
ch
;
boolean
mayBlock
=
true
;
// block on the first read only
do
{
try
{
if
((
ch
=
__read
(
mayBlock
))
<
0
)
{
// must be EOF
if
(
ch
!=
WOULD_BLOCK
)
{
return
(
ch
);
}
}
}
catch
(
InterruptedIOException
e
)
{
synchronized
(
__queue
)
{
__ioException
=
e
;
__queue
.
notifyAll
();
try
{
__queue
.
wait
(
100
);
}
catch
(
InterruptedException
interrupted
)
{
// Ignored
}
}
return
EOF
;
}
try
{
if
(
ch
!=
WOULD_BLOCK
)
{
__processChar
(
ch
);
}
}
catch
(
InterruptedException
e
)
{
if
(
__isClosed
)
{
return
EOF
;
}
}
// Reads should not block on subsequent iterations. Potentially, this could happen if the
// remaining buffered socket data consists entirely of Telnet command sequence and no "user" data.
mayBlock
=
false
;
}
// Continue reading as long as there is data available and the queue is not full.
while
(
super
.
available
()
>
0
&&
__bytesAvailable
<
__queue
.
length
-
1
);
__readIsWaiting
=
false
;
}
continue
;
}
else
{
int
ch
;
ch
=
__queue
[
__queueHead
];
if
(++
__queueHead
>=
__queue
.
length
)
{
__queueHead
=
0
;
}
--
__bytesAvailable
;
// Need to explicitly notify() so available() works properly
if
(
__bytesAvailable
==
0
&&
__threaded
)
{
__queue
.
notify
();
}
return
ch
;
}
}
}
}
/***
* Reads the next number of bytes from the stream into an array and
* returns the number of bytes read. Returns -1 if the end of the
* stream has been reached.
* <p>
* @param buffer The byte array in which to store the data.
* @return The number of bytes read. Returns -1 if the
* end of the message has been reached.
* @exception IOException If an error occurs in reading the underlying
* stream.
***/
@Override
public
int
read
(
byte
buffer
[])
throws
IOException
{
return
read
(
buffer
,
0
,
buffer
.
length
);
}
/***
* Reads the next number of bytes from the stream into an array and returns
* the number of bytes read. Returns -1 if the end of the
* message has been reached. The characters are stored in the array
* starting from the given offset and up to the length specified.
* <p>
* @param buffer The byte array in which to store the data.
* @param offset The offset into the array at which to start storing data.
* @param length The number of bytes to read.
* @return The number of bytes read. Returns -1 if the
* end of the stream has been reached.
* @exception IOException If an error occurs while reading the underlying
* stream.
***/
@Override
public
int
read
(
byte
buffer
[],
int
offset
,
int
length
)
throws
IOException
{
int
ch
,
off
;
if
(
length
<
1
)
{
return
0
;
}
// Critical section because run() may change __bytesAvailable
synchronized
(
__queue
)
{
if
(
length
>
__bytesAvailable
)
{
length
=
__bytesAvailable
;
}
}
if
((
ch
=
read
())
==
EOF
)
{
return
EOF
;
}
off
=
offset
;
do
{
buffer
[
offset
++]
=
(
byte
)
ch
;
}
while
(--
length
>
0
&&
(
ch
=
read
())
!=
EOF
);
//__client._spyRead(buffer, off, offset - off);
return
(
offset
-
off
);
}
/*** Returns false. Mark is not supported. ***/
@Override
public
boolean
markSupported
()
{
return
false
;
}
@Override
public
int
available
()
throws
IOException
{
// Critical section because run() may change __bytesAvailable
synchronized
(
__queue
)
{
if
(
__threaded
)
{
// Must not call super.available when running threaded: NET-466
return
__bytesAvailable
;
}
else
{
return
__bytesAvailable
+
super
.
available
();
}
}
}
// Cannot be synchronized. Will cause deadlock if run() is blocked
// in read because BufferedInputStream read() is synchronized.
@Override
public
void
close
()
throws
IOException
{
// Completely disregard the fact thread may still be running.
// We can't afford to block on this close by waiting for
// thread to terminate because few if any JVM's will actually
// interrupt a system read() from the interrupt() method.
super
.
close
();
synchronized
(
__queue
)
{
__hasReachedEOF
=
true
;
__isClosed
=
true
;
if
(
__thread
!=
null
&&
__thread
.
isAlive
())
{
__thread
.
interrupt
();
}
__queue
.
notifyAll
();
}
}
@Override
public
void
run
()
{
int
ch
;
try
{
_outerLoop:
while
(!
__isClosed
)
{
try
{
if
((
ch
=
__read
(
true
))
<
0
)
{
break
;
}
}
catch
(
InterruptedIOException
e
)
{
synchronized
(
__queue
)
{
__ioException
=
e
;
__queue
.
notifyAll
();
try
{
__queue
.
wait
(
100
);
}
catch
(
InterruptedException
interrupted
)
{
if
(
__isClosed
)
{
break
_outerLoop
;
}
}
continue
;
}
}
catch
(
RuntimeException
re
)
{
// We treat any runtime exceptions as though the
// stream has been closed. We close the
// underlying stream just to be sure.
super
.
close
();
// Breaking the loop has the effect of setting
// the state to closed at the end of the method.
break
_outerLoop
;
}
// Process new character
boolean
notify
=
false
;
try
{
notify
=
__processChar
(
ch
);
}
catch
(
InterruptedException
e
)
{
if
(
__isClosed
)
{
break
_outerLoop
;
}
}
// Notify input listener if buffer was previously empty
if
(
notify
)
{
__client
.
notifyInputListener
();
}
}
}
catch
(
IOException
ioe
)
{
synchronized
(
__queue
)
{
__ioException
=
ioe
;
}
__client
.
notifyInputListener
();
}
synchronized
(
__queue
)
{
__isClosed
=
true
;
// Possibly redundant
__hasReachedEOF
=
true
;
__queue
.
notify
();
}
__threaded
=
false
;
}
}
/* Emacs configuration
* Local variables: **
* mode: java **
* c-basic-offset: 4 **
* indent-tabs-mode: nil **
* End: **
*/
client/src/main/java/org/apache/commons/net/telnet/TelnetNotificationHandler.java
0 → 100644
View file @
7c094a26
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org.apache.commons.net.telnet
;
/***
* The TelnetNotificationHandler interface can be used to handle
* notification of options negotiation commands received on a telnet
* session.
* <p>
* The user can implement this interface and register a
* TelnetNotificationHandler by using the registerNotificationHandler()
* of TelnetClient to be notified of option negotiation commands.
***/
public
interface
TelnetNotificationHandler
{
/***
* The remote party sent a DO command.
***/
public
static
final
int
RECEIVED_DO
=
1
;
/***
* The remote party sent a DONT command.
***/
public
static
final
int
RECEIVED_DONT
=
2
;
/***
* The remote party sent a WILL command.
***/
public
static
final
int
RECEIVED_WILL
=
3
;
/***
* The remote party sent a WONT command.
***/
public
static
final
int
RECEIVED_WONT
=
4
;
/***
* The remote party sent a COMMAND.
* @since 2.2
***/
public
static
final
int
RECEIVED_COMMAND
=
5
;
/***
* Callback method called when TelnetClient receives an
* command or option negotiation command
*
* @param negotiation_code - type of (negotiation) command received
* (RECEIVED_DO, RECEIVED_DONT, RECEIVED_WILL, RECEIVED_WONT, RECEIVED_COMMAND)
*
* @param option_code - code of the option negotiated, or the command code itself (e.g. NOP).
***/
public
void
receivedNegotiation
(
int
negotiation_code
,
int
option_code
);
}
client/src/main/java/org/apache/commons/net/telnet/TelnetOption.java
0 → 100644
View file @
7c094a26
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org.apache.commons.net.telnet
;
/***
* The TelnetOption class cannot be instantiated and only serves as a
* storehouse for telnet option constants.
* <p>
* Details regarding Telnet option specification can be found in RFC 855.
*
*
* @see org.apache.commons.net.telnet.Telnet
* @see org.apache.commons.net.telnet.TelnetClient
***/
public
class
TelnetOption
{
/*** The maximum value an option code can have. This value is 255. ***/
public
static
final
int
MAX_OPTION_VALUE
=
255
;
public
static
final
int
BINARY
=
0
;
public
static
final
int
ECHO
=
1
;
public
static
final
int
PREPARE_TO_RECONNECT
=
2
;
public
static
final
int
SUPPRESS_GO_AHEAD
=
3
;
public
static
final
int
APPROXIMATE_MESSAGE_SIZE
=
4
;
public
static
final
int
STATUS
=
5
;
public
static
final
int
TIMING_MARK
=
6
;
public
static
final
int
REMOTE_CONTROLLED_TRANSMISSION
=
7
;
public
static
final
int
NEGOTIATE_OUTPUT_LINE_WIDTH
=
8
;
public
static
final
int
NEGOTIATE_OUTPUT_PAGE_SIZE
=
9
;
public
static
final
int
NEGOTIATE_CARRIAGE_RETURN
=
10
;
public
static
final
int
NEGOTIATE_HORIZONTAL_TAB_STOP
=
11
;
public
static
final
int
NEGOTIATE_HORIZONTAL_TAB
=
12
;
public
static
final
int
NEGOTIATE_FORMFEED
=
13
;
public
static
final
int
NEGOTIATE_VERTICAL_TAB_STOP
=
14
;
public
static
final
int
NEGOTIATE_VERTICAL_TAB
=
15
;
public
static
final
int
NEGOTIATE_LINEFEED
=
16
;
public
static
final
int
EXTENDED_ASCII
=
17
;
public
static
final
int
FORCE_LOGOUT
=
18
;
public
static
final
int
BYTE_MACRO
=
19
;
public
static
final
int
DATA_ENTRY_TERMINAL
=
20
;
public
static
final
int
SUPDUP
=
21
;
public
static
final
int
SUPDUP_OUTPUT
=
22
;
public
static
final
int
SEND_LOCATION
=
23
;
public
static
final
int
TERMINAL_TYPE
=
24
;
public
static
final
int
END_OF_RECORD
=
25
;
public
static
final
int
TACACS_USER_IDENTIFICATION
=
26
;
public
static
final
int
OUTPUT_MARKING
=
27
;
public
static
final
int
TERMINAL_LOCATION_NUMBER
=
28
;
public
static
final
int
REGIME_3270
=
29
;
public
static
final
int
X3_PAD
=
30
;
public
static
final
int
WINDOW_SIZE
=
31
;
public
static
final
int
TERMINAL_SPEED
=
32
;
public
static
final
int
REMOTE_FLOW_CONTROL
=
33
;
public
static
final
int
LINEMODE
=
34
;
public
static
final
int
X_DISPLAY_LOCATION
=
35
;
public
static
final
int
OLD_ENVIRONMENT_VARIABLES
=
36
;
public
static
final
int
AUTHENTICATION
=
37
;
public
static
final
int
ENCRYPTION
=
38
;
public
static
final
int
NEW_ENVIRONMENT_VARIABLES
=
39
;
public
static
final
int
EXTENDED_OPTIONS_LIST
=
255
;
@SuppressWarnings
(
"unused"
)
private
static
final
int
__FIRST_OPTION
=
BINARY
;
private
static
final
int
__LAST_OPTION
=
EXTENDED_OPTIONS_LIST
;
private
static
final
String
__optionString
[]
=
{
"BINARY"
,
"ECHO"
,
"RCP"
,
"SUPPRESS GO AHEAD"
,
"NAME"
,
"STATUS"
,
"TIMING MARK"
,
"RCTE"
,
"NAOL"
,
"NAOP"
,
"NAOCRD"
,
"NAOHTS"
,
"NAOHTD"
,
"NAOFFD"
,
"NAOVTS"
,
"NAOVTD"
,
"NAOLFD"
,
"EXTEND ASCII"
,
"LOGOUT"
,
"BYTE MACRO"
,
"DATA ENTRY TERMINAL"
,
"SUPDUP"
,
"SUPDUP OUTPUT"
,
"SEND LOCATION"
,
"TERMINAL TYPE"
,
"END OF RECORD"
,
"TACACS UID"
,
"OUTPUT MARKING"
,
"TTYLOC"
,
"3270 REGIME"
,
"X.3 PAD"
,
"NAWS"
,
"TSPEED"
,
"LFLOW"
,
"LINEMODE"
,
"XDISPLOC"
,
"OLD-ENVIRON"
,
"AUTHENTICATION"
,
"ENCRYPT"
,
"NEW-ENVIRON"
,
"TN3270E"
,
"XAUTH"
,
"CHARSET"
,
"RSP"
,
"Com Port Control"
,
"Suppress Local Echo"
,
"Start TLS"
,
"KERMIT"
,
"SEND-URL"
,
"FORWARD_X"
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
"TELOPT PRAGMA LOGON"
,
"TELOPT SSPI LOGON"
,
"TELOPT PRAGMA HEARTBEAT"
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
"Extended-Options-List"
};
/***
* Returns the string representation of the telnet protocol option
* corresponding to the given option code.
*
* @param code The option code of the telnet protocol option
* @return The string representation of the telnet protocol option.
***/
public
static
final
String
getOption
(
int
code
)
{
if
(
__optionString
[
code
].
length
()
==
0
)
{
return
"UNASSIGNED"
;
}
else
{
return
__optionString
[
code
];
}
}
/***
* Determines if a given option code is valid. Returns true if valid,
* false if not.
*
* @param code The option code to test.
* @return True if the option code is valid, false if not.
**/
public
static
final
boolean
isValidOption
(
int
code
)
{
return
(
code
<=
__LAST_OPTION
);
}
// Cannot be instantiated
private
TelnetOption
()
{
}
}
client/src/main/java/org/apache/commons/net/telnet/TelnetOptionHandler.java
0 → 100644
View file @
7c094a26
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org.apache.commons.net.telnet
;
/***
* The TelnetOptionHandler class is the base class to be used
* for implementing handlers for telnet options.
* <p>
* TelnetOptionHandler implements basic option handling
* functionality and defines abstract methods that must be
* implemented to define subnegotiation behaviour.
***/
public
abstract
class
TelnetOptionHandler
{
/***
* Option code
***/
private
int
optionCode
=
-
1
;
/***
* true if the option should be activated on the local side
***/
private
boolean
initialLocal
=
false
;
/***
* true if the option should be activated on the remote side
***/
private
boolean
initialRemote
=
false
;
/***
* true if the option should be accepted on the local side
***/
private
boolean
acceptLocal
=
false
;
/***
* true if the option should be accepted on the remote side
***/
private
boolean
acceptRemote
=
false
;
/***
* true if the option is active on the local side
***/
private
boolean
doFlag
=
false
;
/***
* true if the option is active on the remote side
***/
private
boolean
willFlag
=
false
;
/***
* Constructor for the TelnetOptionHandler. Allows defining desired
* initial setting for local/remote activation of this option and
* behaviour in case a local/remote activation request for this
* option is received.
* <p>
* @param optcode - Option code.
* @param initlocal - if set to true, a WILL is sent upon connection.
* @param initremote - if set to true, a DO is sent upon connection.
* @param acceptlocal - if set to true, any DO request is accepted.
* @param acceptremote - if set to true, any WILL request is accepted.
***/
public
TelnetOptionHandler
(
int
optcode
,
boolean
initlocal
,
boolean
initremote
,
boolean
acceptlocal
,
boolean
acceptremote
)
{
optionCode
=
optcode
;
initialLocal
=
initlocal
;
initialRemote
=
initremote
;
acceptLocal
=
acceptlocal
;
acceptRemote
=
acceptremote
;
}
/***
* Returns the option code for this option.
* <p>
* @return Option code.
***/
public
int
getOptionCode
()
{
return
(
optionCode
);
}
/***
* Returns a boolean indicating whether to accept a DO
* request coming from the other end.
* <p>
* @return true if a DO request shall be accepted.
***/
public
boolean
getAcceptLocal
()
{
return
(
acceptLocal
);
}
/***
* Returns a boolean indicating whether to accept a WILL
* request coming from the other end.
* <p>
* @return true if a WILL request shall be accepted.
***/
public
boolean
getAcceptRemote
()
{
return
(
acceptRemote
);
}
/***
* Set behaviour of the option for DO requests coming from
* the other end.
* <p>
* @param accept - if true, subsequent DO requests will be accepted.
***/
public
void
setAcceptLocal
(
boolean
accept
)
{
acceptLocal
=
accept
;
}
/***
* Set behaviour of the option for WILL requests coming from
* the other end.
* <p>
* @param accept - if true, subsequent WILL requests will be accepted.
***/
public
void
setAcceptRemote
(
boolean
accept
)
{
acceptRemote
=
accept
;
}
/***
* Returns a boolean indicating whether to send a WILL request
* to the other end upon connection.
* <p>
* @return true if a WILL request shall be sent upon connection.
***/
public
boolean
getInitLocal
()
{
return
(
initialLocal
);
}
/***
* Returns a boolean indicating whether to send a DO request
* to the other end upon connection.
* <p>
* @return true if a DO request shall be sent upon connection.
***/
public
boolean
getInitRemote
()
{
return
(
initialRemote
);
}
/***
* Tells this option whether to send a WILL request upon connection.
* <p>
* @param init - if true, a WILL request will be sent upon subsequent
* connections.
***/
public
void
setInitLocal
(
boolean
init
)
{
initialLocal
=
init
;
}
/***
* Tells this option whether to send a DO request upon connection.
* <p>
* @param init - if true, a DO request will be sent upon subsequent
* connections.
***/
public
void
setInitRemote
(
boolean
init
)
{
initialRemote
=
init
;
}
/***
* Method called upon reception of a subnegotiation for this option
* coming from the other end.
* <p>
* This implementation returns null, and
* must be overridden by the actual TelnetOptionHandler to specify
* which response must be sent for the subnegotiation request.
* <p>
* @param suboptionData - the sequence received, without IAC SB & IAC SE
* @param suboptionLength - the length of data in suboption_data
* <p>
* @return response to be sent to the subnegotiation sequence. TelnetClient
* will add IAC SB & IAC SE. null means no response
***/
public
int
[]
answerSubnegotiation
(
int
suboptionData
[],
int
suboptionLength
)
{
return
null
;
}
/***
* This method is invoked whenever this option is acknowledged active on
* the local end (TelnetClient sent a WILL, remote side sent a DO).
* The method is used to specify a subnegotiation sequence that will be
* sent by TelnetClient when the option is activated.
* <p>
* This implementation returns null, and must be overriden by
* the actual TelnetOptionHandler to specify
* which response must be sent for the subnegotiation request.
* @return subnegotiation sequence to be sent by TelnetClient. TelnetClient
* will add IAC SB & IAC SE. null means no subnegotiation.
***/
public
int
[]
startSubnegotiationLocal
()
{
return
null
;
}
/***
* This method is invoked whenever this option is acknowledged active on
* the remote end (TelnetClient sent a DO, remote side sent a WILL).
* The method is used to specify a subnegotiation sequence that will be
* sent by TelnetClient when the option is activated.
* <p>
* This implementation returns null, and must be overriden by
* the actual TelnetOptionHandler to specify
* which response must be sent for the subnegotiation request.
* @return subnegotiation sequence to be sent by TelnetClient. TelnetClient
* will add IAC SB & IAC SE. null means no subnegotiation.
***/
public
int
[]
startSubnegotiationRemote
()
{
return
null
;
}
/***
* Returns a boolean indicating whether a WILL request sent to the other
* side has been acknowledged.
* <p>
* @return true if a WILL sent to the other side has been acknowledged.
***/
boolean
getWill
()
{
return
willFlag
;
}
/***
* Tells this option whether a WILL request sent to the other
* side has been acknowledged (invoked by TelnetClient).
* <p>
* @param state - if true, a WILL request has been acknowledged.
***/
void
setWill
(
boolean
state
)
{
willFlag
=
state
;
}
/***
* Returns a boolean indicating whether a DO request sent to the other
* side has been acknowledged.
* <p>
* @return true if a DO sent to the other side has been acknowledged.
***/
boolean
getDo
()
{
return
doFlag
;
}
/***
* Tells this option whether a DO request sent to the other
* side has been acknowledged (invoked by TelnetClient).
* <p>
* @param state - if true, a DO request has been acknowledged.
***/
void
setDo
(
boolean
state
)
{
doFlag
=
state
;
}
}
client/src/main/java/org/apache/commons/net/telnet/TelnetOutputStream.java
0 → 100644
View file @
7c094a26
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org.apache.commons.net.telnet
;
import
java.io.IOException
;
import
java.io.OutputStream
;
/**
* Wraps an output stream.
* <p>
* In binary mode, the only conversion is to double IAC.
* <p>
* In ASCII mode, if convertCRtoCRLF is true (currently always true), any CR is converted to CRLF.
* IACs are doubled.
* Also a bare LF is converted to CRLF and a bare CR is converted to CR\0
* <p>
***/
final
class
TelnetOutputStream
extends
OutputStream
{
private
final
TelnetClient
__client
;
// TODO there does not appear to be any way to change this value - should it be a ctor parameter?
private
final
boolean
__convertCRtoCRLF
=
true
;
private
boolean
__lastWasCR
=
false
;
TelnetOutputStream
(
TelnetClient
client
)
{
__client
=
client
;
}
/***
* Writes a byte to the stream.
* <p>
* @param ch The byte to write.
* @exception IOException If an error occurs while writing to the underlying
* stream.
***/
@Override
public
void
write
(
int
ch
)
throws
IOException
{
synchronized
(
__client
)
{
ch
&=
0xff
;
if
(
__client
.
_requestedWont
(
TelnetOption
.
BINARY
))
// i.e. ASCII
{
if
(
__lastWasCR
)
{
if
(
__convertCRtoCRLF
)
{
__client
.
_sendByte
(
'\n'
);
if
(
ch
==
'\n'
)
// i.e. was CRLF anyway
{
__lastWasCR
=
false
;
return
;
}
}
// __convertCRtoCRLF
else
if
(
ch
!=
'\n'
)
{
__client
.
_sendByte
(
'\0'
);
// RFC854 requires CR NUL for bare CR
}
}
switch
(
ch
)
{
case
'\r'
:
__client
.
_sendByte
(
'\r'
);
__lastWasCR
=
true
;
break
;
case
'\n'
:
if
(!
__lastWasCR
)
{
// convert LF to CRLF
__client
.
_sendByte
(
'\r'
);
}
__client
.
_sendByte
(
ch
);
__lastWasCR
=
false
;
break
;
case
TelnetCommand
.
IAC
:
__client
.
_sendByte
(
TelnetCommand
.
IAC
);
__client
.
_sendByte
(
TelnetCommand
.
IAC
);
__lastWasCR
=
false
;
break
;
default
:
__client
.
_sendByte
(
ch
);
__lastWasCR
=
false
;
break
;
}
}
// end ASCII
else
if
(
ch
==
TelnetCommand
.
IAC
)
{
__client
.
_sendByte
(
ch
);
__client
.
_sendByte
(
TelnetCommand
.
IAC
);
}
else
{
__client
.
_sendByte
(
ch
);
}
}
}
/***
* Writes a byte array to the stream.
* <p>
* @param buffer The byte array to write.
* @exception IOException If an error occurs while writing to the underlying
* stream.
***/
@Override
public
void
write
(
byte
buffer
[])
throws
IOException
{
write
(
buffer
,
0
,
buffer
.
length
);
}
/***
* Writes a number of bytes from a byte array to the stream starting from
* a given offset.
* <p>
* @param buffer The byte array to write.
* @param offset The offset into the array at which to start copying data.
* @param length The number of bytes to write.
* @exception IOException If an error occurs while writing to the underlying
* stream.
***/
@Override
public
void
write
(
byte
buffer
[],
int
offset
,
int
length
)
throws
IOException
{
synchronized
(
__client
)
{
while
(
length
--
>
0
)
{
write
(
buffer
[
offset
++]);
}
}
}
/*** Flushes the stream. ***/
@Override
public
void
flush
()
throws
IOException
{
__client
.
_flushOutputStream
();
}
/*** Closes the stream. ***/
@Override
public
void
close
()
throws
IOException
{
__client
.
_closeOutputStream
();
}
}
client/src/main/java/org/apache/commons/net/telnet/TerminalTypeOptionHandler.java
0 → 100644
View file @
7c094a26
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org.apache.commons.net.telnet
;
/***
* Implements the telnet terminal type option RFC 1091.
***/
public
class
TerminalTypeOptionHandler
extends
TelnetOptionHandler
{
/***
* Terminal type
***/
private
final
String
termType
;
/***
* Terminal type option
***/
protected
static
final
int
TERMINAL_TYPE
=
24
;
/***
* Send (for subnegotiation)
***/
protected
static
final
int
TERMINAL_TYPE_SEND
=
1
;
/***
* Is (for subnegotiation)
***/
protected
static
final
int
TERMINAL_TYPE_IS
=
0
;
/***
* Constructor for the TerminalTypeOptionHandler. Allows defining desired
* initial setting for local/remote activation of this option and
* behaviour in case a local/remote activation request for this
* option is received.
* <p>
* @param termtype - terminal type that will be negotiated.
* @param initlocal - if set to true, a WILL is sent upon connection.
* @param initremote - if set to true, a DO is sent upon connection.
* @param acceptlocal - if set to true, any DO request is accepted.
* @param acceptremote - if set to true, any WILL request is accepted.
***/
public
TerminalTypeOptionHandler
(
String
termtype
,
boolean
initlocal
,
boolean
initremote
,
boolean
acceptlocal
,
boolean
acceptremote
)
{
super
(
TelnetOption
.
TERMINAL_TYPE
,
initlocal
,
initremote
,
acceptlocal
,
acceptremote
);
termType
=
termtype
;
}
/***
* Constructor for the TerminalTypeOptionHandler. Initial and accept
* behaviour flags are set to false
* <p>
* @param termtype - terminal type that will be negotiated.
***/
public
TerminalTypeOptionHandler
(
String
termtype
)
{
super
(
TelnetOption
.
TERMINAL_TYPE
,
false
,
false
,
false
,
false
);
termType
=
termtype
;
}
/***
* Implements the abstract method of TelnetOptionHandler.
* <p>
* @param suboptionData - the sequence received, without IAC SB & IAC SE
* @param suboptionLength - the length of data in suboption_data
* <p>
* @return terminal type information
***/
@Override
public
int
[]
answerSubnegotiation
(
int
suboptionData
[],
int
suboptionLength
)
{
if
((
suboptionData
!=
null
)
&&
(
suboptionLength
>
1
)
&&
(
termType
!=
null
))
{
if
((
suboptionData
[
0
]
==
TERMINAL_TYPE
)
&&
(
suboptionData
[
1
]
==
TERMINAL_TYPE_SEND
))
{
int
response
[]
=
new
int
[
termType
.
length
()
+
2
];
response
[
0
]
=
TERMINAL_TYPE
;
response
[
1
]
=
TERMINAL_TYPE_IS
;
for
(
int
ii
=
0
;
ii
<
termType
.
length
();
ii
++)
{
response
[
ii
+
2
]
=
termType
.
charAt
(
ii
);
}
return
response
;
}
}
return
null
;
}
}
client/src/main/java/org/apache/commons/net/telnet/WindowSizeOptionHandler.java
0 → 100644
View file @
7c094a26
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org.apache.commons.net.telnet
;
/***
* Implements the telnet window size option RFC 1073.
* @version $Id: WindowSizeOptionHandler.java 1697293 2015-08-24 01:01:00Z sebb $
* @since 2.0
***/
public
class
WindowSizeOptionHandler
extends
TelnetOptionHandler
{
/***
* Horizontal Size
***/
private
int
m_nWidth
=
80
;
/***
* Vertical Size
***/
private
int
m_nHeight
=
24
;
/***
* Window size option
***/
protected
static
final
int
WINDOW_SIZE
=
31
;
/***
* Constructor for the WindowSizeOptionHandler. Allows defining desired
* initial setting for local/remote activation of this option and
* behaviour in case a local/remote activation request for this
* option is received.
* <p>
* @param nWidth - Window width.
* @param nHeight - Window Height
* @param initlocal - if set to true, a WILL is sent upon connection.
* @param initremote - if set to true, a DO is sent upon connection.
* @param acceptlocal - if set to true, any DO request is accepted.
* @param acceptremote - if set to true, any WILL request is accepted.
***/
public
WindowSizeOptionHandler
(
int
nWidth
,
int
nHeight
,
boolean
initlocal
,
boolean
initremote
,
boolean
acceptlocal
,
boolean
acceptremote
)
{
super
(
TelnetOption
.
WINDOW_SIZE
,
initlocal
,
initremote
,
acceptlocal
,
acceptremote
);
m_nWidth
=
nWidth
;
m_nHeight
=
nHeight
;
}
/***
* Constructor for the WindowSizeOptionHandler. Initial and accept
* behaviour flags are set to false
* <p>
* @param nWidth - Window width.
* @param nHeight - Window Height
***/
public
WindowSizeOptionHandler
(
int
nWidth
,
int
nHeight
)
{
super
(
TelnetOption
.
WINDOW_SIZE
,
false
,
false
,
false
,
false
);
m_nWidth
=
nWidth
;
m_nHeight
=
nHeight
;
}
/***
* Implements the abstract method of TelnetOptionHandler.
* This will send the client Height and Width to the server.
* <p>
* @return array to send to remote system
***/
@Override
public
int
[]
startSubnegotiationLocal
()
{
int
nCompoundWindowSize
=
m_nWidth
*
0x10000
+
m_nHeight
;
int
nResponseSize
=
5
;
int
nIndex
;
int
nShift
;
int
nTurnedOnBits
;
if
((
m_nWidth
%
0x100
)
==
0xFF
)
{
nResponseSize
+=
1
;
}
if
((
m_nWidth
/
0x100
)
==
0xFF
)
{
nResponseSize
+=
1
;
}
if
((
m_nHeight
%
0x100
)
==
0xFF
)
{
nResponseSize
+=
1
;
}
if
((
m_nHeight
/
0x100
)
==
0xFF
)
{
nResponseSize
+=
1
;
}
//
// allocate response array
//
int
response
[]
=
new
int
[
nResponseSize
];
//
// Build response array.
// ---------------------
// 1. put option name.
// 2. loop through Window size and fill the values,
// 3. duplicate 'ff' if needed.
//
response
[
0
]
=
WINDOW_SIZE
;
// 1 //
for
(
// 2 //
nIndex
=
1
,
nShift
=
24
;
nIndex
<
nResponseSize
;
nIndex
++,
nShift
-=
8
)
{
nTurnedOnBits
=
0xFF
;
nTurnedOnBits
<<=
nShift
;
response
[
nIndex
]
=
(
nCompoundWindowSize
&
nTurnedOnBits
)
>>>
nShift
;
if
(
response
[
nIndex
]
==
0xff
)
{
// 3 //
nIndex
++;
response
[
nIndex
]
=
0xff
;
}
}
return
response
;
}
}
client/src/main/java/org/apache/commons/net/util/ListenerList.java
0 → 100644
View file @
7c094a26
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org.apache.commons.net.util
;
import
java.io.Serializable
;
import
java.util.EventListener
;
import
java.util.Iterator
;
import
java.util.concurrent.CopyOnWriteArrayList
;
/**
*/
public
class
ListenerList
implements
Serializable
,
Iterable
<
EventListener
>
{
private
static
final
long
serialVersionUID
=
-
1934227607974228213L
;
private
final
CopyOnWriteArrayList
<
EventListener
>
__listeners
;
public
ListenerList
()
{
__listeners
=
new
CopyOnWriteArrayList
<
EventListener
>();
}
public
void
addListener
(
EventListener
listener
)
{
__listeners
.
add
(
listener
);
}
public
void
removeListener
(
EventListener
listener
)
{
__listeners
.
remove
(
listener
);
}
public
int
getListenerCount
()
{
return
__listeners
.
size
();
}
/**
* Return an {@link Iterator} for the {@link EventListener} instances.
*
* @return an {@link Iterator} for the {@link EventListener} instances
* @since 2.0
* TODO Check that this is a good defensive strategy
*/
@Override
public
Iterator
<
EventListener
>
iterator
()
{
return
__listeners
.
iterator
();
}
}
common/pom.xml
0 → 100644
View file @
7c094a26
<?xml version="1.0"?>
<project
xmlns=
"http://maven.apache.org/POM/4.0.0"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
>
<modelVersion>
4.0.0
</modelVersion>
<parent>
<groupId>
com.taobao.arthas
</groupId>
<artifactId>
arthas-all
</artifactId>
<version>
${revision}
</version>
<relativePath>
../pom.xml
</relativePath>
</parent>
<artifactId>
arthas-common
</artifactId>
<name>
arthas-common
</name>
<!-- This module can not add any dependencies -->
<build>
<finalName>
arthas-common
</finalName>
<plugins>
<plugin>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-compiler-plugin
</artifactId>
<configuration>
<source>
1.6
</source>
<target>
1.6
</target>
<encoding>
UTF-8
</encoding>
<showDeprecation>
true
</showDeprecation>
</configuration>
</plugin>
</plugins>
</build>
</project>
common/src/main/java/com/taobao/arthas/common/AnsiLog.java
0 → 100644
View file @
7c094a26
package
com.taobao.arthas.common
;
import
java.util.logging.Level
;
import
java.util.regex.Matcher
;
/**
*
* <pre>
* FINEST -> TRACE
* FINER -> DEBUG
* FINE -> DEBUG
* CONFIG -> INFO
* INFO -> INFO
* WARNING -> WARN
* SEVERE -> ERROR
* </pre>
*
* @see org.slf4j.bridge.SLF4JBridgeHandler
* @author hengyunabc 2017-05-03
*
*/
public
abstract
class
AnsiLog
{
static
boolean
enableColor
;
public
static
java
.
util
.
logging
.
Level
LEVEL
=
java
.
util
.
logging
.
Level
.
CONFIG
;
private
static
final
String
RESET
=
"\033[0m"
;
private
static
final
int
DEFAULT
=
39
;
private
static
final
int
BLACK
=
30
;
private
static
final
int
RED
=
31
;
private
static
final
int
GREEN
=
32
;
private
static
final
int
YELLOW
=
33
;
private
static
final
int
BLUE
=
34
;
private
static
final
int
MAGENTA
=
35
;
private
static
final
int
CYAN
=
36
;
private
static
final
int
WHITE
=
37
;
private
static
final
String
TRACE_PREFIX
=
"[TRACE] "
;
private
static
final
String
TRACE_COLOR_PREFIX
=
"["
+
colorStr
(
"TRACE"
,
GREEN
)
+
"] "
;
private
static
final
String
DEBUG_PREFIX
=
"[DEBUG] "
;
private
static
final
String
DEBUG_COLOR_PREFIX
=
"["
+
colorStr
(
"DEBUG"
,
GREEN
)
+
"] "
;
private
static
final
String
INFO_PREFIX
=
"[INFO] "
;
private
static
final
String
INFO_COLOR_PREFIX
=
"["
+
colorStr
(
"INFO"
,
GREEN
)
+
"] "
;
private
static
final
String
WARN_PREFIX
=
"[WARN] "
;
private
static
final
String
WARN_COLOR_PREFIX
=
"["
+
colorStr
(
"WARN"
,
YELLOW
)
+
"] "
;
private
static
final
String
ERROR_PREFIX
=
"[ERROR] "
;
private
static
final
String
ERROR_COLOR_PREFIX
=
"["
+
colorStr
(
"ERROR"
,
RED
)
+
"] "
;
static
{
if
(
System
.
console
()
!=
null
)
{
enableColor
=
true
;
// windows dos, do not support color
if
(
OSUtils
.
isWindows
())
{
enableColor
=
false
;
}
}
// cygwin and mingw support color
if
(
OSUtils
.
isCygwinOrMinGW
())
{
enableColor
=
true
;
}
}
private
AnsiLog
()
{
}
public
static
boolean
enableColor
()
{
return
enableColor
;
}
/**
* set logger Level
*
* @see java.util.logging.Level
* @param level
* @return
*/
public
static
Level
level
(
Level
level
)
{
Level
old
=
LEVEL
;
LEVEL
=
level
;
return
old
;
}
/**
* get current logger Level
*
* @return
*/
public
static
Level
level
()
{
return
LEVEL
;
}
public
static
String
black
(
String
msg
)
{
if
(
enableColor
)
{
return
colorStr
(
msg
,
BLACK
);
}
else
{
return
msg
;
}
}
public
static
String
red
(
String
msg
)
{
if
(
enableColor
)
{
return
colorStr
(
msg
,
RED
);
}
else
{
return
msg
;
}
}
public
static
String
green
(
String
msg
)
{
if
(
enableColor
)
{
return
colorStr
(
msg
,
GREEN
);
}
else
{
return
msg
;
}
}
public
static
String
yellow
(
String
msg
)
{
if
(
enableColor
)
{
return
colorStr
(
msg
,
YELLOW
);
}
else
{
return
msg
;
}
}
public
static
String
blue
(
String
msg
)
{
if
(
enableColor
)
{
return
colorStr
(
msg
,
BLUE
);
}
else
{
return
msg
;
}
}
public
static
String
magenta
(
String
msg
)
{
if
(
enableColor
)
{
return
colorStr
(
msg
,
MAGENTA
);
}
else
{
return
msg
;
}
}
public
static
String
cyan
(
String
msg
)
{
if
(
enableColor
)
{
return
colorStr
(
msg
,
CYAN
);
}
else
{
return
msg
;
}
}
public
static
String
white
(
String
msg
)
{
if
(
enableColor
)
{
return
colorStr
(
msg
,
WHITE
);
}
else
{
return
msg
;
}
}
private
static
String
colorStr
(
String
msg
,
int
colorCode
)
{
return
"\033["
+
colorCode
+
"m"
+
msg
+
RESET
;
}
public
static
void
trace
(
String
msg
)
{
if
(
canLog
(
Level
.
FINEST
))
{
if
(
enableColor
)
{
System
.
out
.
println
(
TRACE_COLOR_PREFIX
+
msg
);
}
else
{
System
.
out
.
println
(
TRACE_PREFIX
+
msg
);
}
}
}
public
static
void
trace
(
String
format
,
Object
...
arguments
)
{
if
(
canLog
(
Level
.
FINEST
))
{
trace
(
format
(
format
,
arguments
));
}
}
public
static
void
trace
(
Throwable
t
)
{
if
(
canLog
(
Level
.
FINEST
))
{
t
.
printStackTrace
(
System
.
out
);
}
}
public
static
void
debug
(
String
msg
)
{
if
(
canLog
(
Level
.
FINER
))
{
if
(
enableColor
)
{
System
.
out
.
println
(
DEBUG_COLOR_PREFIX
+
msg
);
}
else
{
System
.
out
.
println
(
DEBUG_PREFIX
+
msg
);
}
}
}
public
static
void
debug
(
String
format
,
Object
...
arguments
)
{
if
(
canLog
(
Level
.
FINER
))
{
debug
(
format
(
format
,
arguments
));
}
}
public
static
void
debug
(
Throwable
t
)
{
if
(
canLog
(
Level
.
FINER
))
{
t
.
printStackTrace
(
System
.
out
);
}
}
public
static
void
info
(
String
msg
)
{
if
(
canLog
(
Level
.
CONFIG
))
{
if
(
enableColor
)
{
System
.
out
.
println
(
INFO_COLOR_PREFIX
+
msg
);
}
else
{
System
.
out
.
println
(
INFO_PREFIX
+
msg
);
}
}
}
public
static
void
info
(
String
format
,
Object
...
arguments
)
{
if
(
canLog
(
Level
.
CONFIG
))
{
info
(
format
(
format
,
arguments
));
}
}
public
static
void
info
(
Throwable
t
)
{
if
(
canLog
(
Level
.
CONFIG
))
{
t
.
printStackTrace
(
System
.
out
);
}
}
public
static
void
warn
(
String
msg
)
{
if
(
canLog
(
Level
.
WARNING
))
{
if
(
enableColor
)
{
System
.
out
.
println
(
WARN_COLOR_PREFIX
+
msg
);
}
else
{
System
.
out
.
println
(
WARN_PREFIX
+
msg
);
}
}
}
public
static
void
warn
(
String
format
,
Object
...
arguments
)
{
if
(
canLog
(
Level
.
WARNING
))
{
warn
(
format
(
format
,
arguments
));
}
}
public
static
void
warn
(
Throwable
t
)
{
if
(
canLog
(
Level
.
WARNING
))
{
t
.
printStackTrace
(
System
.
out
);
}
}
public
static
void
error
(
String
msg
)
{
if
(
canLog
(
Level
.
SEVERE
))
{
if
(
enableColor
)
{
System
.
out
.
println
(
ERROR_COLOR_PREFIX
+
msg
);
}
else
{
System
.
out
.
println
(
ERROR_PREFIX
+
msg
);
}
}
}
public
static
void
error
(
String
format
,
Object
...
arguments
)
{
if
(
canLog
(
Level
.
SEVERE
))
{
error
(
format
(
format
,
arguments
));
}
}
public
static
void
error
(
Throwable
t
)
{
if
(
canLog
(
Level
.
SEVERE
))
{
t
.
printStackTrace
(
System
.
out
);
}
}
private
static
String
format
(
String
from
,
Object
...
arguments
)
{
if
(
from
!=
null
)
{
String
computed
=
from
;
if
(
arguments
!=
null
&&
arguments
.
length
!=
0
)
{
for
(
Object
argument
:
arguments
)
{
computed
=
computed
.
replaceFirst
(
"\\{\\}"
,
Matcher
.
quoteReplacement
(
argument
.
toString
()));
}
}
return
computed
;
}
return
null
;
}
private
static
boolean
canLog
(
Level
level
)
{
return
level
.
intValue
()
>=
LEVEL
.
intValue
();
}
}
common/src/main/java/com/taobao/arthas/common/ArthasConstants.java
0 → 100644
View file @
7c094a26
package
com.taobao.arthas.common
;
/**
*
* @author hengyunabc 2020-09-02
*
*/
public
class
ArthasConstants
{
/**
* local address in VM communication
*
* @see io.netty.channel.local.LocalAddress
* @see io.netty.channel.local.LocalChannel
*/
public
static
final
String
NETTY_LOCAL_ADDRESS
=
"arthas-netty-LocalAddress"
;
public
static
final
int
MAX_HTTP_CONTENT_LENGTH
=
1024
*
1024
*
10
;
public
static
final
String
ARTHAS_OUTPUT
=
"arthas-output"
;
public
static
final
String
APP_NAME
=
"app-name"
;
public
static
final
String
PROJECT_NAME
=
"project.name"
;
public
static
final
String
SPRING_APPLICATION_NAME
=
"spring.application.name"
;
public
static
final
int
TELNET_PORT
=
3658
;
public
static
final
String
DEFAULT_WEBSOCKET_PATH
=
"/ws"
;
public
static
final
int
WEBSOCKET_IDLE_SECONDS
=
60
;
/**
* HTTP cookie id
*/
public
static
final
String
ASESSION_KEY
=
"asession"
;
public
static
final
String
DEFAULT_USERNAME
=
"arthas"
;
public
static
final
String
SUBJECT_KEY
=
"subject"
;
public
static
final
String
AUTH
=
"auth"
;
public
static
final
String
USERNAME_KEY
=
"username"
;
public
static
final
String
PASSWORD_KEY
=
"password"
;
}
common/src/main/java/com/taobao/arthas/common/ExecutingCommand.java
0 → 100644
View file @
7c094a26
package
com.taobao.arthas.common
;
import
java.io.BufferedReader
;
import
java.io.IOException
;
import
java.io.InputStreamReader
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.List
;
/**
* A class for executing on the command line and returning the result of
* execution.
*
* @author alessandro[at]perucchi[dot]org
*/
public
class
ExecutingCommand
{
private
ExecutingCommand
()
{
}
/**
* Executes a command on the native command line and returns the result.
*
* @param cmdToRun
* Command to run
* @return A list of Strings representing the result of the command, or empty
* string if the command failed
*/
public
static
List
<
String
>
runNative
(
String
cmdToRun
)
{
String
[]
cmd
=
cmdToRun
.
split
(
" "
);
return
runNative
(
cmd
);
}
/**
* Executes a command on the native command line and returns the result line by
* line.
*
* @param cmdToRunWithArgs
* Command to run and args, in an array
* @return A list of Strings representing the result of the command, or empty
* string if the command failed
*/
public
static
List
<
String
>
runNative
(
String
[]
cmdToRunWithArgs
)
{
Process
p
=
null
;
try
{
p
=
Runtime
.
getRuntime
().
exec
(
cmdToRunWithArgs
);
}
catch
(
SecurityException
e
)
{
AnsiLog
.
trace
(
"Couldn't run command {}:"
,
Arrays
.
toString
(
cmdToRunWithArgs
));
AnsiLog
.
trace
(
e
);
return
new
ArrayList
<
String
>(
0
);
}
catch
(
IOException
e
)
{
AnsiLog
.
trace
(
"Couldn't run command {}:"
,
Arrays
.
toString
(
cmdToRunWithArgs
));
AnsiLog
.
trace
(
e
);
return
new
ArrayList
<
String
>(
0
);
}
ArrayList
<
String
>
sa
=
new
ArrayList
<
String
>();
BufferedReader
reader
=
new
BufferedReader
(
new
InputStreamReader
(
p
.
getInputStream
()));
try
{
String
line
;
while
((
line
=
reader
.
readLine
())
!=
null
)
{
sa
.
add
(
line
);
}
p
.
waitFor
();
}
catch
(
IOException
e
)
{
AnsiLog
.
trace
(
"Problem reading output from {}:"
,
Arrays
.
toString
(
cmdToRunWithArgs
));
AnsiLog
.
trace
(
e
);
return
new
ArrayList
<
String
>(
0
);
}
catch
(
InterruptedException
ie
)
{
AnsiLog
.
trace
(
"Problem reading output from {}:"
,
Arrays
.
toString
(
cmdToRunWithArgs
));
AnsiLog
.
trace
(
ie
);
Thread
.
currentThread
().
interrupt
();
}
finally
{
IOUtils
.
close
(
reader
);
}
return
sa
;
}
/**
* Return first line of response for selected command.
*
* @param cmd2launch
* String command to be launched
* @return String or empty string if command failed
*/
public
static
String
getFirstAnswer
(
String
cmd2launch
)
{
return
getAnswerAt
(
cmd2launch
,
0
);
}
/**
* Return response on selected line index (0-based) after running selected
* command.
*
* @param cmd2launch
* String command to be launched
* @param answerIdx
* int index of line in response of the command
* @return String whole line in response or empty string if invalid index or
* running of command fails
*/
public
static
String
getAnswerAt
(
String
cmd2launch
,
int
answerIdx
)
{
List
<
String
>
sa
=
ExecutingCommand
.
runNative
(
cmd2launch
);
if
(
answerIdx
>=
0
&&
answerIdx
<
sa
.
size
())
{
return
sa
.
get
(
answerIdx
);
}
return
""
;
}
}
common/src/main/java/com/taobao/arthas/common/FileUtils.java
0 → 100644
View file @
7c094a26
package
com.taobao.arthas.common
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.io.FileOutputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
/**
*
* @see org.apache.commons.io.FileUtils
* @author hengyunabc 2020-05-03
*
*/
public
class
FileUtils
{
public
static
File
getTempDirectory
()
{
return
new
File
(
System
.
getProperty
(
"java.io.tmpdir"
));
}
/**
* Writes a byte array to a file creating the file if it does not exist.
* <p>
* NOTE: As from v1.3, the parent directories of the file will be created if
* they do not exist.
*
* @param file the file to write to
* @param data the content to write to the file
* @throws IOException in case of an I/O error
* @since 1.1
*/
public
static
void
writeByteArrayToFile
(
final
File
file
,
final
byte
[]
data
)
throws
IOException
{
writeByteArrayToFile
(
file
,
data
,
false
);
}
/**
* Writes a byte array to a file creating the file if it does not exist.
*
* @param file the file to write to
* @param data the content to write to the file
* @param append if {@code true}, then bytes will be added to the end of the
* file rather than overwriting
* @throws IOException in case of an I/O error
* @since 2.1
*/
public
static
void
writeByteArrayToFile
(
final
File
file
,
final
byte
[]
data
,
final
boolean
append
)
throws
IOException
{
writeByteArrayToFile
(
file
,
data
,
0
,
data
.
length
,
append
);
}
/**
* Writes {@code len} bytes from the specified byte array starting at offset
* {@code off} to a file, creating the file if it does not exist.
*
* @param file the file to write to
* @param data the content to write to the file
* @param off the start offset in the data
* @param len the number of bytes to write
* @throws IOException in case of an I/O error
* @since 2.5
*/
public
static
void
writeByteArrayToFile
(
final
File
file
,
final
byte
[]
data
,
final
int
off
,
final
int
len
)
throws
IOException
{
writeByteArrayToFile
(
file
,
data
,
off
,
len
,
false
);
}
/**
* Writes {@code len} bytes from the specified byte array starting at offset
* {@code off} to a file, creating the file if it does not exist.
*
* @param file the file to write to
* @param data the content to write to the file
* @param off the start offset in the data
* @param len the number of bytes to write
* @param append if {@code true}, then bytes will be added to the end of the
* file rather than overwriting
* @throws IOException in case of an I/O error
* @since 2.5
*/
public
static
void
writeByteArrayToFile
(
final
File
file
,
final
byte
[]
data
,
final
int
off
,
final
int
len
,
final
boolean
append
)
throws
IOException
{
FileOutputStream
out
=
null
;
try
{
out
=
openOutputStream
(
file
,
append
);
out
.
write
(
data
,
off
,
len
);
}
finally
{
IOUtils
.
close
(
out
);
}
}
/**
* Opens a {@link FileOutputStream} for the specified file, checking and
* creating the parent directory if it does not exist.
* <p>
* At the end of the method either the stream will be successfully opened, or an
* exception will have been thrown.
* <p>
* The parent directory will be created if it does not exist. The file will be
* created if it does not exist. An exception is thrown if the file object
* exists but is a directory. An exception is thrown if the file exists but
* cannot be written to. An exception is thrown if the parent directory cannot
* be created.
*
* @param file the file to open for output, must not be {@code null}
* @param append if {@code true}, then bytes will be added to the end of the
* file rather than overwriting
* @return a new {@link FileOutputStream} for the specified file
* @throws IOException if the file object is a directory
* @throws IOException if the file cannot be written to
* @throws IOException if a parent directory needs creating but that fails
* @since 2.1
*/
public
static
FileOutputStream
openOutputStream
(
final
File
file
,
final
boolean
append
)
throws
IOException
{
if
(
file
.
exists
())
{
if
(
file
.
isDirectory
())
{
throw
new
IOException
(
"File '"
+
file
+
"' exists but is a directory"
);
}
if
(!
file
.
canWrite
())
{
throw
new
IOException
(
"File '"
+
file
+
"' cannot be written to"
);
}
}
else
{
final
File
parent
=
file
.
getParentFile
();
if
(
parent
!=
null
)
{
if
(!
parent
.
mkdirs
()
&&
!
parent
.
isDirectory
())
{
throw
new
IOException
(
"Directory '"
+
parent
+
"' could not be created"
);
}
}
}
return
new
FileOutputStream
(
file
,
append
);
}
/**
* Reads the contents of a file into a byte array.
* The file is always closed.
*
* @param file the file to read, must not be {@code null}
* @return the file contents, never {@code null}
* @throws IOException in case of an I/O error
* @since 1.1
*/
public
static
byte
[]
readFileToByteArray
(
final
File
file
)
throws
IOException
{
InputStream
in
=
null
;
try
{
in
=
new
FileInputStream
(
file
);
return
IOUtils
.
getBytes
(
in
);
}
finally
{
IOUtils
.
close
(
in
);
}
}
}
common/src/main/java/com/taobao/arthas/common/IOUtils.java
0 → 100644
View file @
7c094a26
package
com.taobao.arthas.common
;
import
java.io.BufferedInputStream
;
import
java.io.BufferedOutputStream
;
import
java.io.ByteArrayOutputStream
;
import
java.io.Closeable
;
import
java.io.File
;
import
java.io.FileOutputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.OutputStream
;
import
java.io.Reader
;
import
java.io.Writer
;
import
java.util.Enumeration
;
import
java.util.zip.ZipEntry
;
import
java.util.zip.ZipFile
;
/**
*
* @author hengyunabc 2018-11-06
*
*/
public
class
IOUtils
{
private
IOUtils
()
{
}
public
static
String
toString
(
InputStream
inputStream
)
throws
IOException
{
ByteArrayOutputStream
result
=
new
ByteArrayOutputStream
();
byte
[]
buffer
=
new
byte
[
1024
];
int
length
;
while
((
length
=
inputStream
.
read
(
buffer
))
!=
-
1
)
{
result
.
write
(
buffer
,
0
,
length
);
}
return
result
.
toString
(
"UTF-8"
);
}
public
static
void
copy
(
InputStream
in
,
OutputStream
out
)
throws
IOException
{
byte
[]
buffer
=
new
byte
[
1024
];
int
len
;
while
((
len
=
in
.
read
(
buffer
))
!=
-
1
)
{
out
.
write
(
buffer
,
0
,
len
);
}
}
/**
* @return a byte[] containing the information contained in the specified
* InputStream.
* @throws java.io.IOException
*/
public
static
byte
[]
getBytes
(
InputStream
input
)
throws
IOException
{
ByteArrayOutputStream
result
=
new
ByteArrayOutputStream
();
copy
(
input
,
result
);
result
.
close
();
return
result
.
toByteArray
();
}
public
static
IOException
close
(
InputStream
input
)
{
return
close
((
Closeable
)
input
);
}
public
static
IOException
close
(
OutputStream
output
)
{
return
close
((
Closeable
)
output
);
}
public
static
IOException
close
(
final
Reader
input
)
{
return
close
((
Closeable
)
input
);
}
public
static
IOException
close
(
final
Writer
output
)
{
return
close
((
Closeable
)
output
);
}
public
static
IOException
close
(
final
Closeable
closeable
)
{
try
{
if
(
closeable
!=
null
)
{
closeable
.
close
();
}
}
catch
(
final
IOException
ioe
)
{
return
ioe
;
}
return
null
;
}
// support jdk6
public
static
IOException
close
(
final
ZipFile
zip
)
{
try
{
if
(
zip
!=
null
)
{
zip
.
close
();
}
}
catch
(
final
IOException
ioe
)
{
return
ioe
;
}
return
null
;
}
public
static
boolean
isSubFile
(
File
parent
,
File
child
)
throws
IOException
{
return
child
.
getCanonicalPath
().
startsWith
(
parent
.
getCanonicalPath
()
+
File
.
separator
);
}
public
static
boolean
isSubFile
(
String
parent
,
String
child
)
throws
IOException
{
return
isSubFile
(
new
File
(
parent
),
new
File
(
child
));
}
public
static
void
unzip
(
String
zipFile
,
String
extractFolder
)
throws
IOException
{
File
file
=
new
File
(
zipFile
);
ZipFile
zip
=
null
;
try
{
int
BUFFER
=
1024
*
8
;
zip
=
new
ZipFile
(
file
);
File
newPath
=
new
File
(
extractFolder
);
newPath
.
mkdirs
();
Enumeration
<?
extends
ZipEntry
>
zipFileEntries
=
zip
.
entries
();
// Process each entry
while
(
zipFileEntries
.
hasMoreElements
())
{
// grab a zip file entry
ZipEntry
entry
=
(
ZipEntry
)
zipFileEntries
.
nextElement
();
String
currentEntry
=
entry
.
getName
();
File
destFile
=
new
File
(
newPath
,
currentEntry
);
if
(!
isSubFile
(
newPath
,
destFile
))
{
throw
new
IOException
(
"Bad zip entry: "
+
currentEntry
);
}
// destFile = new File(newPath, destFile.getName());
File
destinationParent
=
destFile
.
getParentFile
();
// create the parent directory structure if needed
destinationParent
.
mkdirs
();
if
(!
entry
.
isDirectory
())
{
BufferedInputStream
is
=
null
;
BufferedOutputStream
dest
=
null
;
try
{
is
=
new
BufferedInputStream
(
zip
.
getInputStream
(
entry
));
int
currentByte
;
// establish buffer for writing file
byte
data
[]
=
new
byte
[
BUFFER
];
// write the current file to disk
FileOutputStream
fos
=
new
FileOutputStream
(
destFile
);
dest
=
new
BufferedOutputStream
(
fos
,
BUFFER
);
// read and write until last byte is encountered
while
((
currentByte
=
is
.
read
(
data
,
0
,
BUFFER
))
!=
-
1
)
{
dest
.
write
(
data
,
0
,
currentByte
);
}
dest
.
flush
();
}
finally
{
close
(
dest
);
close
(
is
);
}
}
}
}
finally
{
close
(
zip
);
}
}
}
common/src/main/java/com/taobao/arthas/common/JavaVersionUtils.java
0 → 100644
View file @
7c094a26
package
com.taobao.arthas.common
;
import
java.util.Properties
;
/**
*
* @author hengyunabc 2018-11-21
*
*/
public
class
JavaVersionUtils
{
private
static
final
String
VERSION_PROP_NAME
=
"java.specification.version"
;
private
static
final
String
JAVA_VERSION_STR
=
System
.
getProperty
(
VERSION_PROP_NAME
);
private
static
final
float
JAVA_VERSION
=
Float
.
parseFloat
(
JAVA_VERSION_STR
);
private
JavaVersionUtils
()
{
}
public
static
String
javaVersionStr
()
{
return
JAVA_VERSION_STR
;
}
public
static
String
javaVersionStr
(
Properties
props
)
{
return
(
null
!=
props
)
?
props
.
getProperty
(
VERSION_PROP_NAME
):
null
;
}
public
static
float
javaVersion
()
{
return
JAVA_VERSION
;
}
public
static
boolean
isJava6
()
{
return
JAVA_VERSION_STR
.
equals
(
"1.6"
);
}
public
static
boolean
isJava7
()
{
return
JAVA_VERSION_STR
.
equals
(
"1.7"
);
}
public
static
boolean
isJava8
()
{
return
JAVA_VERSION_STR
.
equals
(
"1.8"
);
}
public
static
boolean
isJava9
()
{
return
JAVA_VERSION_STR
.
equals
(
"9"
);
}
public
static
boolean
isLessThanJava9
()
{
return
JAVA_VERSION
<
9.0f
;
}
public
static
boolean
isGreaterThanJava7
()
{
return
JAVA_VERSION
>
1.7f
;
}
public
static
boolean
isGreaterThanJava8
()
{
return
JAVA_VERSION
>
1.8f
;
}
public
static
boolean
isGreaterThanJava11
()
{
return
JAVA_VERSION
>
11.0f
;
}
}
common/src/main/java/com/taobao/arthas/common/OSUtils.java
0 → 100644
View file @
7c094a26
package
com.taobao.arthas.common
;
import
java.util.Locale
;
/**
*
* @author hengyunabc 2018-11-08
*
*/
public
class
OSUtils
{
private
static
final
String
OPERATING_SYSTEM_NAME
=
System
.
getProperty
(
"os.name"
).
toLowerCase
(
Locale
.
ENGLISH
);
private
static
final
String
OPERATING_SYSTEM_ARCH
=
System
.
getProperty
(
"os.arch"
).
toLowerCase
(
Locale
.
ENGLISH
);
private
static
final
String
UNKNOWN
=
"unknown"
;
static
PlatformEnum
platform
;
static
String
arch
;
static
{
if
(
OPERATING_SYSTEM_NAME
.
startsWith
(
"linux"
))
{
platform
=
PlatformEnum
.
LINUX
;
}
else
if
(
OPERATING_SYSTEM_NAME
.
startsWith
(
"mac"
)
||
OPERATING_SYSTEM_NAME
.
startsWith
(
"darwin"
))
{
platform
=
PlatformEnum
.
MACOSX
;
}
else
if
(
OPERATING_SYSTEM_NAME
.
startsWith
(
"windows"
))
{
platform
=
PlatformEnum
.
WINDOWS
;
}
else
{
platform
=
PlatformEnum
.
UNKNOWN
;
}
arch
=
normalizeArch
(
OPERATING_SYSTEM_ARCH
);
}
private
OSUtils
()
{
}
public
static
boolean
isWindows
()
{
return
platform
==
PlatformEnum
.
WINDOWS
;
}
public
static
boolean
isLinux
()
{
return
platform
==
PlatformEnum
.
LINUX
;
}
public
static
boolean
isMac
()
{
return
platform
==
PlatformEnum
.
MACOSX
;
}
public
static
boolean
isCygwinOrMinGW
()
{
if
(
isWindows
())
{
if
((
System
.
getenv
(
"MSYSTEM"
)
!=
null
&&
System
.
getenv
(
"MSYSTEM"
).
startsWith
(
"MINGW"
))
||
"/bin/bash"
.
equals
(
System
.
getenv
(
"SHELL"
)))
{
return
true
;
}
}
return
false
;
}
public
static
String
arch
()
{
return
arch
;
}
public
static
boolean
isArm32
()
{
return
"arm_32"
.
equals
(
arch
);
}
public
static
boolean
isArm64
()
{
return
"aarch_64"
.
equals
(
arch
);
}
private
static
String
normalizeArch
(
String
value
)
{
value
=
normalize
(
value
);
if
(
value
.
matches
(
"^(x8664|amd64|ia32e|em64t|x64)$"
))
{
return
"x86_64"
;
}
if
(
value
.
matches
(
"^(x8632|x86|i[3-6]86|ia32|x32)$"
))
{
return
"x86_32"
;
}
if
(
value
.
matches
(
"^(ia64w?|itanium64)$"
))
{
return
"itanium_64"
;
}
if
(
"ia64n"
.
equals
(
value
))
{
return
"itanium_32"
;
}
if
(
value
.
matches
(
"^(sparc|sparc32)$"
))
{
return
"sparc_32"
;
}
if
(
value
.
matches
(
"^(sparcv9|sparc64)$"
))
{
return
"sparc_64"
;
}
if
(
value
.
matches
(
"^(arm|arm32)$"
))
{
return
"arm_32"
;
}
if
(
"aarch64"
.
equals
(
value
))
{
return
"aarch_64"
;
}
if
(
value
.
matches
(
"^(mips|mips32)$"
))
{
return
"mips_32"
;
}
if
(
value
.
matches
(
"^(mipsel|mips32el)$"
))
{
return
"mipsel_32"
;
}
if
(
"mips64"
.
equals
(
value
))
{
return
"mips_64"
;
}
if
(
"mips64el"
.
equals
(
value
))
{
return
"mipsel_64"
;
}
if
(
value
.
matches
(
"^(ppc|ppc32)$"
))
{
return
"ppc_32"
;
}
if
(
value
.
matches
(
"^(ppcle|ppc32le)$"
))
{
return
"ppcle_32"
;
}
if
(
"ppc64"
.
equals
(
value
))
{
return
"ppc_64"
;
}
if
(
"ppc64le"
.
equals
(
value
))
{
return
"ppcle_64"
;
}
if
(
"s390"
.
equals
(
value
))
{
return
"s390_32"
;
}
if
(
"s390x"
.
equals
(
value
))
{
return
"s390_64"
;
}
return
UNKNOWN
;
}
private
static
String
normalize
(
String
value
)
{
if
(
value
==
null
)
{
return
""
;
}
return
value
.
toLowerCase
(
Locale
.
US
).
replaceAll
(
"[^a-z0-9]+"
,
""
);
}
}
common/src/main/java/com/taobao/arthas/common/Pair.java
0 → 100644
View file @
7c094a26
package
com.taobao.arthas.common
;
public
class
Pair
<
X
,
Y
>
{
private
final
X
x
;
private
final
Y
y
;
public
Pair
(
X
x
,
Y
y
)
{
this
.
x
=
x
;
this
.
y
=
y
;
}
public
X
getFirst
()
{
return
x
;
}
public
Y
getSecond
()
{
return
y
;
}
public
static
<
A
,
B
>
Pair
<
A
,
B
>
make
(
A
a
,
B
b
)
{
return
new
Pair
<
A
,
B
>(
a
,
b
);
}
@Override
public
boolean
equals
(
Object
o
)
{
if
(
o
==
this
)
return
true
;
if
(!(
o
instanceof
Pair
))
return
false
;
Pair
other
=
(
Pair
)
o
;
if
(
x
==
null
)
{
if
(
other
.
x
!=
null
)
return
false
;
}
else
{
if
(!
x
.
equals
(
other
.
x
))
return
false
;
}
if
(
y
==
null
)
{
if
(
other
.
y
!=
null
)
return
false
;
}
else
{
if
(!
y
.
equals
(
other
.
y
))
return
false
;
}
return
true
;
}
@Override
public
int
hashCode
()
{
int
hashCode
=
1
;
if
(
x
!=
null
)
hashCode
=
x
.
hashCode
();
if
(
y
!=
null
)
hashCode
=
(
hashCode
*
31
)
+
y
.
hashCode
();
return
hashCode
;
}
@Override
public
String
toString
()
{
return
"P["
+
x
+
","
+
y
+
"]"
;
}
}
Prev
1
2
3
4
5
6
7
8
9
10
…
19
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment