Toggle navigation
Toggle navigation
This project
Loading...
Sign in
grogv3
/
grog-cubi
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Authored by
JR Utily
2017-04-23 10:48:56 +0200
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
c615dd5f31964de6dac703e1ce3a13bcd38db3a6
c615dd5f
1 parent
e8aef6f1
simplify H2 console, and deploy it only when in Integration project stage
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
22 additions
and
3944 deletions
grog-webapp/src/main/java/org/legrog/util/ConnectionInfo.java
grog-webapp/src/main/java/org/legrog/util/H2ConsoleServlet.java
grog-webapp/src/main/java/org/legrog/util/PageParser.java
grog-webapp/src/main/java/org/legrog/util/WebApp.java
grog-webapp/src/main/java/org/legrog/util/WebServer.java
grog-webapp/src/main/java/org/legrog/util/WebSession.java
grog-webapp/src/main/java/org/legrog/util/WebThread.java
grog-webapp/src/main/java/org/legrog/util/ConnectionInfo.java
deleted
100644 → 0
View file @
e8aef6f
package
org
.
legrog
.
util
;
// Code copied from org.h2.server.web.ConnectionInfo
/*
* Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
//package org.h2.server.web;
import
org.h2.util.MathUtils
;
import
org.h2.util.StringUtils
;
/**
* The connection info object is a wrapper for database connection information
* such as the database URL, user name and password.
* This class is used by the H2 Console.
*/
public
class
ConnectionInfo
implements
Comparable
<
ConnectionInfo
>
{
/**
* The driver class name.
*/
public
String
driver
;
/**
* The database URL.
*/
public
String
url
;
/**
* The user name.
*/
public
String
user
;
/**
* The connection display name.
*/
String
name
;
/**
* The last time this connection was used.
*/
int
lastAccess
;
ConnectionInfo
()
{
// nothing to do
}
public
ConnectionInfo
(
String
data
)
{
String
[]
array
=
StringUtils
.
arraySplit
(
data
,
'|'
,
false
);
name
=
get
(
array
,
0
);
driver
=
get
(
array
,
1
);
url
=
get
(
array
,
2
);
user
=
get
(
array
,
3
);
}
private
static
String
get
(
String
[]
array
,
int
i
)
{
return
array
!=
null
&&
array
.
length
>
i
?
array
[
i
]
:
""
;
}
String
getString
()
{
return
StringUtils
.
arrayCombine
(
new
String
[]
{
name
,
driver
,
url
,
user
},
'|'
);
}
@Override
public
int
compareTo
(
ConnectionInfo
o
)
{
return
-
MathUtils
.
compareInt
(
lastAccess
,
o
.
lastAccess
);
}
}
\ No newline at end of file
grog-webapp/src/main/java/org/legrog/util/H2ConsoleServlet.java
View file @
c615dd5
package
org
.
legrog
.
util
;
import
javax.servlet.annotation.WebServlet
;
import
java.io.IOException
;
import
java.net.InetAddress
;
import
java.net.UnknownHostException
;
import
java.util.ArrayList
;
import
java.util.Enumeration
;
import
java.util.Properties
;
import
org.apache.deltaspike.core.api.projectstage.ProjectStage
;
import
org.apache.deltaspike.core.util.ProjectStageProducer
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
javax.servlet.ServletConfig
;
import
javax.servlet.ServletOutputStream
;
import
javax.servlet.http.HttpServlet
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
javax.servlet.annotation.WebInitParam
;
import
javax.servlet.annotation.WebServlet
;
import
org.h2.engine.Constants
;
import
org.h2.server.web.PageParser
;
import
org.h2.util.New
;
import
static
org
.
legrog
.
util
.
H2ConsoleServlet
.
CONSOLE_MAPPING
;
@WebServlet
(
urlPatterns
=
"/console/*"
,
name
=
"H2Console"
,
loadOnStartup
=
1
)
public
class
H2ConsoleServlet
extends
HttpServlet
{
// Code copied from org.h2.server.web.WebServlet
private
static
final
long
serialVersionUID
=
1L
;
private
transient
WebServer
server
;
@WebServlet
(
urlPatterns
=
CONSOLE_MAPPING
,
name
=
"H2Console"
,
loadOnStartup
=
1
,
initParams
=
{
@WebInitParam
(
name
=
"webAllowOthers"
,
value
=
""
),
@WebInitParam
(
name
=
"trace"
,
value
=
""
)}
)
public
class
H2ConsoleServlet
extends
org
.
h2
.
server
.
web
.
WebServlet
{
static
final
String
CONSOLE_MAPPING
=
"/console/*"
;
private
Logger
logger
=
LoggerFactory
.
getLogger
(
getClass
());
@Override
public
void
init
()
{
ServletConfig
config
=
getServletConfig
();
Enumeration
<?>
en
=
config
.
getInitParameterNames
();
ArrayList
<
String
>
list
=
New
.
arrayList
();
while
(
en
.
hasMoreElements
())
{
String
name
=
en
.
nextElement
().
toString
();
String
value
=
config
.
getInitParameter
(
name
);
if
(!
name
.
startsWith
(
"-"
))
{
name
=
"-"
+
name
;
}
list
.
add
(
name
);
if
(
value
.
length
()
>
0
)
{
list
.
add
(
value
);
}
}
String
[]
args
=
new
String
[
list
.
size
()];
list
.
toArray
(
args
);
server
=
new
WebServer
();
server
.
setAllowChunked
(
false
);
server
.
init
(
args
);
}
@Override
public
void
destroy
()
{
server
.
stop
();
}
private
boolean
allow
(
HttpServletRequest
req
)
{
if
(
server
.
getAllowOthers
())
{
return
true
;
}
String
addr
=
req
.
getRemoteAddr
();
try
{
InetAddress
address
=
InetAddress
.
getByName
(
addr
);
return
address
.
isLoopbackAddress
();
}
catch
(
UnknownHostException
e
)
{
return
false
;
}
catch
(
NoClassDefFoundError
e
)
{
// Google App Engine does not allow java.net.InetAddress
return
false
;
}
}
private
String
getAllowedFile
(
HttpServletRequest
req
,
String
requestedFile
)
{
if
(!
allow
(
req
))
{
return
"notAllowed.jsp"
;
}
if
(
requestedFile
.
length
()
==
0
)
{
return
"index.do"
;
}
return
requestedFile
;
}
@Override
public
void
doGet
(
HttpServletRequest
req
,
HttpServletResponse
resp
)
throws
IOException
{
req
.
setCharacterEncoding
(
"utf-8"
);
String
file
=
req
.
getPathInfo
();
if
(
file
==
null
)
{
resp
.
sendRedirect
(
req
.
getRequestURI
()
+
"/"
);
return
;
}
else
if
(
file
.
startsWith
(
"/"
))
{
file
=
file
.
substring
(
1
);
}
file
=
getAllowedFile
(
req
,
file
);
// extract the request attributes
Properties
attributes
=
new
Properties
();
Enumeration
<?>
en
=
req
.
getAttributeNames
();
while
(
en
.
hasMoreElements
())
{
String
name
=
en
.
nextElement
().
toString
();
String
value
=
req
.
getAttribute
(
name
).
toString
();
attributes
.
put
(
name
,
value
);
}
en
=
req
.
getParameterNames
();
while
(
en
.
hasMoreElements
())
{
String
name
=
en
.
nextElement
().
toString
();
String
value
=
req
.
getParameter
(
name
);
attributes
.
put
(
name
,
value
);
}
WebSession
session
=
null
;
String
sessionId
=
attributes
.
getProperty
(
"jsessionid"
);
if
(
sessionId
!=
null
)
{
session
=
server
.
getSession
(
sessionId
);
}
WebApp
app
=
new
WebApp
(
server
);
app
.
setSession
(
session
,
attributes
);
String
ifModifiedSince
=
req
.
getHeader
(
"if-modified-since"
);
String
hostAddr
=
req
.
getRemoteAddr
();
file
=
app
.
processRequest
(
file
,
hostAddr
);
session
=
app
.
getSession
();
String
mimeType
=
app
.
getMimeType
();
boolean
cache
=
app
.
getCache
();
if
(
cache
&&
server
.
getStartDateTime
().
equals
(
ifModifiedSince
))
{
resp
.
setStatus
(
HttpServletResponse
.
SC_NOT_MODIFIED
);
return
;
}
byte
[]
bytes
=
server
.
getFile
(
file
);
if
(
bytes
==
null
)
{
resp
.
sendError
(
HttpServletResponse
.
SC_NOT_FOUND
);
bytes
=
(
"File not found: "
+
file
).
getBytes
(
Constants
.
UTF8
);
ProjectStage
projectStage
=
ProjectStageProducer
.
getInstance
().
getProjectStage
();
if
(
projectStage
==
ProjectStage
.
IntegrationTest
)
{
logger
.
info
(
"Create a H2 Console Servlet mapped to {}"
,
CONSOLE_MAPPING
);
super
.
init
();
}
else
{
if
(
session
!=
null
&&
file
.
endsWith
(
".jsp"
))
{
String
page
=
new
String
(
bytes
,
Constants
.
UTF8
);
page
=
PageParser
.
parse
(
page
,
session
.
map
);
bytes
=
page
.
getBytes
(
Constants
.
UTF8
);
}
resp
.
setContentType
(
mimeType
);
if
(!
cache
)
{
resp
.
setHeader
(
"Cache-Control"
,
"no-cache"
);
}
else
{
resp
.
setHeader
(
"Cache-Control"
,
"max-age=10"
);
resp
.
setHeader
(
"Last-Modified"
,
server
.
getStartDateTime
());
}
logger
.
info
(
"Skipping H2 Console Servlet creation"
);
}
if
(
bytes
!=
null
)
{
ServletOutputStream
out
=
resp
.
getOutputStream
();
out
.
write
(
bytes
);
}
}
@Override
public
void
doPost
(
HttpServletRequest
req
,
HttpServletResponse
resp
)
throws
IOException
{
doGet
(
req
,
resp
);
}
}
...
...
grog-webapp/src/main/java/org/legrog/util/PageParser.java
deleted
100644 → 0
View file @
e8aef6f
package
org
.
legrog
.
util
;
// Code copied from org.h2.server.web.PageParser
/*
* Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
//package org.h2.server.web;
import
java.text.ParseException
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
org.h2.util.New
;
/**
* A page parser can parse an HTML page and replace the tags there.
* This class is used by the H2 Console.
*/
public
class
PageParser
{
private
static
final
int
TAB_WIDTH
=
4
;
private
final
String
page
;
private
int
pos
;
private
final
Map
<
String
,
Object
>
settings
;
private
final
int
len
;
private
StringBuilder
result
;
private
PageParser
(
String
page
,
Map
<
String
,
Object
>
settings
,
int
pos
)
{
this
.
page
=
page
;
this
.
pos
=
pos
;
this
.
len
=
page
.
length
();
this
.
settings
=
settings
;
result
=
new
StringBuilder
(
len
);
}
/**
* Replace the tags in the HTML page with the given settings.
*
* @param page the HTML page
* @param settings the settings
* @return the converted page
*/
public
static
String
parse
(
String
page
,
Map
<
String
,
Object
>
settings
)
{
PageParser
block
=
new
PageParser
(
page
,
settings
,
0
);
return
block
.
replaceTags
();
}
private
void
setError
(
int
i
)
{
String
s
=
page
.
substring
(
0
,
i
)
+
"####BUG####"
+
page
.
substring
(
i
);
s
=
PageParser
.
escapeHtml
(
s
);
result
=
new
StringBuilder
();
result
.
append
(
s
);
}
private
String
parseBlockUntil
(
String
end
)
throws
ParseException
{
PageParser
block
=
new
PageParser
(
page
,
settings
,
pos
);
block
.
parseAll
();
if
(!
block
.
readIf
(
end
))
{
throw
new
ParseException
(
page
,
block
.
pos
);
}
pos
=
block
.
pos
;
return
block
.
result
.
toString
();
}
private
String
replaceTags
()
{
try
{
parseAll
();
if
(
pos
!=
len
)
{
setError
(
pos
);
}
}
catch
(
ParseException
e
)
{
setError
(
pos
);
}
return
result
.
toString
();
}
@SuppressWarnings
(
"unchecked"
)
private
void
parseAll
()
throws
ParseException
{
StringBuilder
buff
=
result
;
String
p
=
page
;
int
i
=
pos
;
for
(;
i
<
len
;
i
++)
{
char
c
=
p
.
charAt
(
i
);
switch
(
c
)
{
case
'<'
:
{
if
(
p
.
charAt
(
i
+
3
)
==
':'
&&
p
.
charAt
(
i
+
1
)
==
'/'
)
{
// end tag
pos
=
i
;
return
;
}
else
if
(
p
.
charAt
(
i
+
2
)
==
':'
)
{
pos
=
i
;
if
(
readIf
(
"<c:forEach"
))
{
String
var
=
readParam
(
"var"
);
String
items
=
readParam
(
"items"
);
read
(
">"
);
int
start
=
pos
;
List
<
Object
>
list
=
(
List
<
Object
>)
get
(
items
);
if
(
list
==
null
)
{
result
.
append
(
"?items?"
);
list
=
New
.
arrayList
();
}
if
(
list
.
size
()
==
0
)
{
parseBlockUntil
(
"</c:forEach>"
);
}
for
(
Object
o
:
list
)
{
settings
.
put
(
var
,
o
);
pos
=
start
;
String
block
=
parseBlockUntil
(
"</c:forEach>"
);
result
.
append
(
block
);
}
}
else
if
(
readIf
(
"<c:if"
))
{
String
test
=
readParam
(
"test"
);
int
eq
=
test
.
indexOf
(
"=='"
);
if
(
eq
<
0
)
{
setError
(
i
);
return
;
}
String
val
=
test
.
substring
(
eq
+
3
,
test
.
length
()
-
1
);
test
=
test
.
substring
(
0
,
eq
);
String
value
=
(
String
)
get
(
test
);
read
(
">"
);
String
block
=
parseBlockUntil
(
"</c:if>"
);
pos
--;
if
(
value
.
equals
(
val
))
{
result
.
append
(
block
);
}
}
else
{
setError
(
i
);
return
;
}
i
=
pos
;
}
else
{
buff
.
append
(
c
);
}
break
;
}
case
'$'
:
if
(
p
.
length
()
>
i
+
1
&&
p
.
charAt
(
i
+
1
)
==
'{'
)
{
i
+=
2
;
int
j
=
p
.
indexOf
(
'}'
,
i
);
if
(
j
<
0
)
{
setError
(
i
);
return
;
}
String
item
=
p
.
substring
(
i
,
j
).
trim
();
i
=
j
;
String
s
=
(
String
)
get
(
item
);
replaceTags
(
s
);
}
else
{
buff
.
append
(
c
);
}
break
;
default
:
buff
.
append
(
c
);
break
;
}
}
pos
=
i
;
}
@SuppressWarnings
(
"unchecked"
)
private
Object
get
(
String
item
)
{
int
dot
=
item
.
indexOf
(
'.'
);
if
(
dot
>=
0
)
{
String
sub
=
item
.
substring
(
dot
+
1
);
item
=
item
.
substring
(
0
,
dot
);
HashMap
<
String
,
Object
>
map
=
(
HashMap
<
String
,
Object
>)
settings
.
get
(
item
);
if
(
map
==
null
)
{
return
"?"
+
item
+
"?"
;
}
return
map
.
get
(
sub
);
}
return
settings
.
get
(
item
);
}
private
void
replaceTags
(
String
s
)
{
if
(
s
!=
null
)
{
result
.
append
(
PageParser
.
parse
(
s
,
settings
));
}
}
private
String
readParam
(
String
name
)
throws
ParseException
{
read
(
name
);
read
(
"="
);
read
(
"\""
);
int
start
=
pos
;
while
(
page
.
charAt
(
pos
)
!=
'"'
)
{
pos
++;
}
int
end
=
pos
;
read
(
"\""
);
String
s
=
page
.
substring
(
start
,
end
);
return
PageParser
.
parse
(
s
,
settings
);
}
private
void
skipSpaces
()
{
while
(
page
.
charAt
(
pos
)
==
' '
)
{
pos
++;
}
}
private
void
read
(
String
s
)
throws
ParseException
{
if
(!
readIf
(
s
))
{
throw
new
ParseException
(
s
,
pos
);
}
}
private
boolean
readIf
(
String
s
)
{
skipSpaces
();
if
(
page
.
regionMatches
(
pos
,
s
,
0
,
s
.
length
()))
{
pos
+=
s
.
length
();
skipSpaces
();
return
true
;
}
return
false
;
}
/**
* Convert data to HTML, but don't convert newlines and multiple spaces.
*
* @param s the data
* @return the escaped html text
*/
static
String
escapeHtmlData
(
String
s
)
{
return
escapeHtml
(
s
,
false
);
}
/**
* Convert data to HTML, including newlines and multiple spaces.
*
* @param s the data
* @return the escaped html text
*/
public
static
String
escapeHtml
(
String
s
)
{
return
escapeHtml
(
s
,
true
);
}
private
static
String
escapeHtml
(
String
s
,
boolean
convertBreakAndSpace
)
{
if
(
s
==
null
)
{
return
null
;
}
if
(
convertBreakAndSpace
)
{
if
(
s
.
length
()
==
0
)
{
return
" "
;
}
}
StringBuilder
buff
=
new
StringBuilder
(
s
.
length
());
boolean
convertSpace
=
true
;
for
(
int
i
=
0
;
i
<
s
.
length
();
i
++)
{
char
c
=
s
.
charAt
(
i
);
if
(
c
==
' '
||
c
==
'\t'
)
{
// convert tabs into spaces
for
(
int
j
=
0
;
j
<
(
c
==
' '
?
1
:
TAB_WIDTH
);
j
++)
{
if
(
convertSpace
&&
convertBreakAndSpace
)
{
buff
.
append
(
" "
);
}
else
{
buff
.
append
(
' '
);
convertSpace
=
true
;
}
}
continue
;
}
convertSpace
=
false
;
switch
(
c
)
{
case
'$'
:
// so that ${ } in the text is interpreted correctly
buff
.
append
(
"$"
);
break
;
case
'<'
:
buff
.
append
(
"<"
);
break
;
case
'>'
:
buff
.
append
(
">"
);
break
;
case
'&'
:
buff
.
append
(
"&"
);
break
;
case
'"'
:
buff
.
append
(
"""
);
break
;
case
'\''
:
buff
.
append
(
"'"
);
break
;
case
'\n'
:
if
(
convertBreakAndSpace
)
{
buff
.
append
(
"<br />"
);
convertSpace
=
true
;
}
else
{
buff
.
append
(
c
);
}
break
;
default
:
if
(
c
>=
128
)
{
buff
.
append
(
"&#"
).
append
((
int
)
c
).
append
(
';'
);
}
else
{
buff
.
append
(
c
);
}
break
;
}
}
return
buff
.
toString
();
}
/**
* Escape text as a the javascript string.
*
* @param s the text
* @return the javascript string
*/
static
String
escapeJavaScript
(
String
s
)
{
if
(
s
==
null
)
{
return
null
;
}
if
(
s
.
length
()
==
0
)
{
return
""
;
}
StringBuilder
buff
=
new
StringBuilder
(
s
.
length
());
for
(
int
i
=
0
;
i
<
s
.
length
();
i
++)
{
char
c
=
s
.
charAt
(
i
);
switch
(
c
)
{
case
'"'
:
buff
.
append
(
"\\\""
);
break
;
case
'\''
:
buff
.
append
(
"\\'"
);
break
;
case
'\\'
:
buff
.
append
(
"\\\\"
);
break
;
case
'\n'
:
buff
.
append
(
"\\n"
);
break
;
case
'\r'
:
buff
.
append
(
"\\r"
);
break
;
case
'\t'
:
buff
.
append
(
"\\t"
);
break
;
default
:
buff
.
append
(
c
);
break
;
}
}
return
buff
.
toString
();
}
}
\ No newline at end of file
grog-webapp/src/main/java/org/legrog/util/WebApp.java
deleted
100644 → 0
View file @
e8aef6f
package
org
.
legrog
.
util
;
// Code copied from org.h2.server.web.WebApp
/*
* Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
//package org.h2.server.web;
import
java.io.ByteArrayOutputStream
;
import
java.io.PrintStream
;
import
java.io.PrintWriter
;
import
java.io.StringReader
;
import
java.io.StringWriter
;
import
java.lang.reflect.InvocationTargetException
;
import
java.lang.reflect.Method
;
import
java.math.BigDecimal
;
import
java.sql.Connection
;
import
java.sql.DatabaseMetaData
;
import
java.sql.ParameterMetaData
;
import
java.sql.PreparedStatement
;
import
java.sql.ResultSet
;
import
java.sql.ResultSetMetaData
;
import
java.sql.SQLException
;
import
java.sql.Statement
;
import
java.sql.Types
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.Comparator
;
import
java.util.HashMap
;
import
java.util.Iterator
;
import
java.util.Locale
;
import
java.util.Map
;
import
java.util.Properties
;
import
java.util.Random
;
import
org.h2.api.ErrorCode
;
import
org.h2.bnf.Bnf
;
import
org.h2.bnf.context.DbColumn
;
import
org.h2.bnf.context.DbContents
;
import
org.h2.bnf.context.DbSchema
;
import
org.h2.bnf.context.DbTableOrView
;
import
org.h2.engine.Constants
;
import
org.h2.engine.SysProperties
;
import
org.h2.jdbc.JdbcSQLException
;
import
org.h2.message.DbException
;
import
org.h2.security.SHA256
;
import
org.h2.tools.Backup
;
import
org.h2.tools.ChangeFileEncryption
;
import
org.h2.tools.ConvertTraceFile
;
import
org.h2.tools.CreateCluster
;
import
org.h2.tools.DeleteDbFiles
;
import
org.h2.tools.Recover
;
import
org.h2.tools.Restore
;
import
org.h2.tools.RunScript
;
import
org.h2.tools.Script
;
import
org.h2.tools.SimpleResultSet
;
import
org.h2.util.JdbcUtils
;
import
org.h2.util.New
;
import
org.h2.util.Profiler
;
import
org.h2.util.ScriptReader
;
import
org.h2.util.SortedProperties
;
import
org.h2.util.StatementBuilder
;
import
org.h2.util.StringUtils
;
import
org.h2.util.Tool
;
import
org.h2.util.Utils
;
/**
* For each connection to a session, an object of this class is created.
* This class is used by the H2 Console.
*/
public
class
WebApp
{
/**
* The web server.
*/
protected
final
WebServer
server
;
/**
* The session.
*/
protected
WebSession
session
;
/**
* The session attributes
*/
protected
Properties
attributes
;
/**
* The mime type of the current response.
*/
protected
String
mimeType
;
/**
* Whether the response can be cached.
*/
protected
boolean
cache
;
/**
* Whether to close the connection.
*/
protected
boolean
stop
;
/**
* The language in the HTTP header.
*/
protected
String
headerLanguage
;
private
Profiler
profiler
;
WebApp
(
WebServer
server
)
{
this
.
server
=
server
;
}
/**
* Set the web session and attributes.
*
* @param session the session
* @param attributes the attributes
*/
void
setSession
(
WebSession
session
,
Properties
attributes
)
{
this
.
session
=
session
;
this
.
attributes
=
attributes
;
}
/**
* Process an HTTP request.
*
* @param file the file that was requested
* @param hostAddr the host address
* @return the name of the file to return to the client
*/
String
processRequest
(
String
file
,
String
hostAddr
)
{
int
index
=
file
.
lastIndexOf
(
'.'
);
String
suffix
;
if
(
index
>=
0
)
{
suffix
=
file
.
substring
(
index
+
1
);
}
else
{
suffix
=
""
;
}
if
(
"ico"
.
equals
(
suffix
))
{
mimeType
=
"image/x-icon"
;
cache
=
true
;
}
else
if
(
"gif"
.
equals
(
suffix
))
{
mimeType
=
"image/gif"
;
cache
=
true
;
}
else
if
(
"css"
.
equals
(
suffix
))
{
cache
=
true
;
mimeType
=
"text/css"
;
}
else
if
(
"html"
.
equals
(
suffix
)
||
"do"
.
equals
(
suffix
)
||
"jsp"
.
equals
(
suffix
))
{
cache
=
false
;
mimeType
=
"text/html"
;
if
(
session
==
null
)
{
session
=
server
.
createNewSession
(
hostAddr
);
if
(!
"notAllowed.jsp"
.
equals
(
file
))
{
file
=
"index.do"
;
}
}
}
else
if
(
"js"
.
equals
(
suffix
))
{
cache
=
true
;
mimeType
=
"text/javascript"
;
}
else
{
cache
=
true
;
mimeType
=
"application/octet-stream"
;
}
trace
(
"mimeType="
+
mimeType
);
trace
(
file
);
if
(
file
.
endsWith
(
".do"
))
{
file
=
process
(
file
);
}
return
file
;
}
private
static
String
getComboBox
(
String
[]
elements
,
String
selected
)
{
StringBuilder
buff
=
new
StringBuilder
();
for
(
String
value
:
elements
)
{
buff
.
append
(
"<option value=\""
).
append
(
PageParser
.
escapeHtmlData
(
value
)).
append
(
'\"'
);
if
(
value
.
equals
(
selected
))
{
buff
.
append
(
" selected"
);
}
buff
.
append
(
'>'
).
append
(
PageParser
.
escapeHtml
(
value
)).
append
(
"</option>"
);
}
return
buff
.
toString
();
}
private
static
String
getComboBox
(
String
[][]
elements
,
String
selected
)
{
StringBuilder
buff
=
new
StringBuilder
();
for
(
String
[]
n
:
elements
)
{
buff
.
append
(
"<option value=\""
).
append
(
PageParser
.
escapeHtmlData
(
n
[
0
])).
append
(
'\"'
);
if
(
n
[
0
].
equals
(
selected
))
{
buff
.
append
(
" selected"
);
}
buff
.
append
(
'>'
).
append
(
PageParser
.
escapeHtml
(
n
[
1
])).
append
(
"</option>"
);
}
return
buff
.
toString
();
}
private
String
process
(
String
file
)
{
trace
(
"process "
+
file
);
while
(
file
.
endsWith
(
".do"
))
{
if
(
"login.do"
.
equals
(
file
))
{
file
=
login
();
}
else
if
(
"index.do"
.
equals
(
file
))
{
file
=
index
();
}
else
if
(
"logout.do"
.
equals
(
file
))
{
file
=
logout
();
}
else
if
(
"settingRemove.do"
.
equals
(
file
))
{
file
=
settingRemove
();
}
else
if
(
"settingSave.do"
.
equals
(
file
))
{
file
=
settingSave
();
}
else
if
(
"test.do"
.
equals
(
file
))
{
file
=
test
();
}
else
if
(
"query.do"
.
equals
(
file
))
{
file
=
query
();
}
else
if
(
"tables.do"
.
equals
(
file
))
{
file
=
tables
();
}
else
if
(
"editResult.do"
.
equals
(
file
))
{
file
=
editResult
();
}
else
if
(
"getHistory.do"
.
equals
(
file
))
{
file
=
getHistory
();
}
else
if
(
"admin.do"
.
equals
(
file
))
{
file
=
admin
();
}
else
if
(
"adminSave.do"
.
equals
(
file
))
{
file
=
adminSave
();
}
else
if
(
"adminStartTranslate.do"
.
equals
(
file
))
{
file
=
adminStartTranslate
();
}
else
if
(
"adminShutdown.do"
.
equals
(
file
))
{
file
=
adminShutdown
();
}
else
if
(
"autoCompleteList.do"
.
equals
(
file
))
{
file
=
autoCompleteList
();
}
else
if
(
"tools.do"
.
equals
(
file
))
{
file
=
tools
();
}
else
{
file
=
"error.jsp"
;
}
}
trace
(
"return "
+
file
);
return
file
;
}
private
String
autoCompleteList
()
{
String
query
=
(
String
)
attributes
.
get
(
"query"
);
boolean
lowercase
=
false
;
if
(
query
.
trim
().
length
()
>
0
&&
Character
.
isLowerCase
(
query
.
trim
().
charAt
(
0
)))
{
lowercase
=
true
;
}
try
{
String
sql
=
query
;
if
(
sql
.
endsWith
(
";"
))
{
sql
+=
" "
;
}
ScriptReader
reader
=
new
ScriptReader
(
new
StringReader
(
sql
));
reader
.
setSkipRemarks
(
true
);
String
lastSql
=
""
;
while
(
true
)
{
String
n
=
reader
.
readStatement
();
if
(
n
==
null
)
{
break
;
}
lastSql
=
n
;
}
String
result
=
""
;
if
(
reader
.
isInsideRemark
())
{
if
(
reader
.
isBlockRemark
())
{
result
=
"1#(End Remark)# */\n"
+
result
;
}
else
{
result
=
"1#(Newline)#\n"
+
result
;
}
}
else
{
sql
=
lastSql
;
while
(
sql
.
length
()
>
0
&&
sql
.
charAt
(
0
)
<=
' '
)
{
sql
=
sql
.
substring
(
1
);
}
if
(
sql
.
trim
().
length
()
>
0
&&
Character
.
isLowerCase
(
sql
.
trim
().
charAt
(
0
)))
{
lowercase
=
true
;
}
Bnf
bnf
=
session
.
getBnf
();
if
(
bnf
==
null
)
{
return
"autoCompleteList.jsp"
;
}
HashMap
<
String
,
String
>
map
=
bnf
.
getNextTokenList
(
sql
);
String
space
=
""
;
if
(
sql
.
length
()
>
0
)
{
char
last
=
sql
.
charAt
(
sql
.
length
()
-
1
);
if
(!
Character
.
isWhitespace
(
last
)
&&
(
last
!=
'.'
&&
last
>=
' '
&&
last
!=
'\''
&&
last
!=
'"'
))
{
space
=
" "
;
}
}
ArrayList
<
String
>
list
=
New
.
arrayList
(
map
.
size
());
for
(
Map
.
Entry
<
String
,
String
>
entry
:
map
.
entrySet
())
{
String
key
=
entry
.
getKey
();
String
value
=
entry
.
getValue
();
String
type
=
""
+
key
.
charAt
(
0
);
if
(
Integer
.
parseInt
(
type
)
>
2
)
{
continue
;
}
key
=
key
.
substring
(
2
);
if
(
Character
.
isLetter
(
key
.
charAt
(
0
))
&&
lowercase
)
{
key
=
StringUtils
.
toLowerEnglish
(
key
);
value
=
StringUtils
.
toLowerEnglish
(
value
);
}
if
(
key
.
equals
(
value
)
&&
!
"."
.
equals
(
value
))
{
value
=
space
+
value
;
}
key
=
StringUtils
.
urlEncode
(
key
);
key
=
StringUtils
.
replaceAll
(
key
,
"+"
,
" "
);
value
=
StringUtils
.
urlEncode
(
value
);
value
=
StringUtils
.
replaceAll
(
value
,
"+"
,
" "
);
list
.
add
(
type
+
"#"
+
key
+
"#"
+
value
);
}
Collections
.
sort
(
list
);
if
(
query
.
endsWith
(
"\n"
)
||
query
.
trim
().
endsWith
(
";"
))
{
list
.
add
(
0
,
"1#(Newline)#\n"
);
}
StatementBuilder
buff
=
new
StatementBuilder
();
for
(
String
s
:
list
)
{
buff
.
appendExceptFirst
(
"|"
);
buff
.
append
(
s
);
}
result
=
buff
.
toString
();
}
session
.
put
(
"autoCompleteList"
,
result
);
}
catch
(
Throwable
e
)
{
server
.
traceError
(
e
);
}
return
"autoCompleteList.jsp"
;
}
private
String
admin
()
{
session
.
put
(
"port"
,
""
+
server
.
getPort
());
session
.
put
(
"allowOthers"
,
""
+
server
.
getAllowOthers
());
session
.
put
(
"ssl"
,
String
.
valueOf
(
server
.
getSSL
()));
session
.
put
(
"sessions"
,
server
.
getSessions
());
return
"admin.jsp"
;
}
private
String
adminSave
()
{
try
{
Properties
prop
=
new
SortedProperties
();
int
port
=
Integer
.
decode
((
String
)
attributes
.
get
(
"port"
));
prop
.
setProperty
(
"webPort"
,
String
.
valueOf
(
port
));
server
.
setPort
(
port
);
boolean
allowOthers
=
Boolean
.
parseBoolean
(
(
String
)
attributes
.
get
(
"allowOthers"
));
prop
.
setProperty
(
"webAllowOthers"
,
String
.
valueOf
(
allowOthers
));
server
.
setAllowOthers
(
allowOthers
);
boolean
ssl
=
Boolean
.
parseBoolean
(
(
String
)
attributes
.
get
(
"ssl"
));
prop
.
setProperty
(
"webSSL"
,
String
.
valueOf
(
ssl
));
server
.
setSSL
(
ssl
);
server
.
saveProperties
(
prop
);
}
catch
(
Exception
e
)
{
trace
(
e
.
toString
());
}
return
admin
();
}
private
String
tools
()
{
try
{
String
toolName
=
(
String
)
attributes
.
get
(
"tool"
);
session
.
put
(
"tool"
,
toolName
);
String
args
=
(
String
)
attributes
.
get
(
"args"
);
String
[]
argList
=
StringUtils
.
arraySplit
(
args
,
','
,
false
);
Tool
tool
=
null
;
if
(
"Backup"
.
equals
(
toolName
))
{
tool
=
new
Backup
();
}
else
if
(
"Restore"
.
equals
(
toolName
))
{
tool
=
new
Restore
();
}
else
if
(
"Recover"
.
equals
(
toolName
))
{
tool
=
new
Recover
();
}
else
if
(
"DeleteDbFiles"
.
equals
(
toolName
))
{
tool
=
new
DeleteDbFiles
();
}
else
if
(
"ChangeFileEncryption"
.
equals
(
toolName
))
{
tool
=
new
ChangeFileEncryption
();
}
else
if
(
"Script"
.
equals
(
toolName
))
{
tool
=
new
Script
();
}
else
if
(
"RunScript"
.
equals
(
toolName
))
{
tool
=
new
RunScript
();
}
else
if
(
"ConvertTraceFile"
.
equals
(
toolName
))
{
tool
=
new
ConvertTraceFile
();
}
else
if
(
"CreateCluster"
.
equals
(
toolName
))
{
tool
=
new
CreateCluster
();
}
else
{
throw
DbException
.
throwInternalError
(
toolName
);
}
ByteArrayOutputStream
outBuff
=
new
ByteArrayOutputStream
();
PrintStream
out
=
new
PrintStream
(
outBuff
,
false
,
"UTF-8"
);
tool
.
setOut
(
out
);
try
{
tool
.
runTool
(
argList
);
out
.
flush
();
String
o
=
new
String
(
outBuff
.
toByteArray
(),
Constants
.
UTF8
);
String
result
=
PageParser
.
escapeHtml
(
o
);
session
.
put
(
"toolResult"
,
result
);
}
catch
(
Exception
e
)
{
session
.
put
(
"toolResult"
,
getStackTrace
(
0
,
e
,
true
));
}
}
catch
(
Exception
e
)
{
server
.
traceError
(
e
);
}
return
"tools.jsp"
;
}
private
String
adminStartTranslate
()
{
Map
<?,
?>
p
=
Map
.
class
.
cast
(
session
.
map
.
get
(
"text"
));
@SuppressWarnings
(
"unchecked"
)
Map
<
Object
,
Object
>
p2
=
(
Map
<
Object
,
Object
>)
p
;
String
file
=
server
.
startTranslate
(
p2
);
session
.
put
(
"translationFile"
,
file
);
return
"helpTranslate.jsp"
;
}
/**
* Stop the application and the server.
*
* @return the page to display
*/
protected
String
adminShutdown
()
{
server
.
shutdown
();
return
"admin.jsp"
;
}
private
String
index
()
{
String
[][]
languageArray
=
WebServer
.
LANGUAGES
;
String
language
=
(
String
)
attributes
.
get
(
"language"
);
Locale
locale
=
session
.
locale
;
if
(
language
!=
null
)
{
if
(
locale
==
null
||
!
StringUtils
.
toLowerEnglish
(
locale
.
getLanguage
()).
equals
(
language
))
{
locale
=
new
Locale
(
language
,
""
);
server
.
readTranslations
(
session
,
locale
.
getLanguage
());
session
.
put
(
"language"
,
language
);
session
.
locale
=
locale
;
}
}
else
{
language
=
(
String
)
session
.
get
(
"language"
);
}
if
(
language
==
null
)
{
// if the language is not yet known
// use the last header
language
=
headerLanguage
;
}
session
.
put
(
"languageCombo"
,
getComboBox
(
languageArray
,
language
));
String
[]
settingNames
=
server
.
getSettingNames
();
String
setting
=
attributes
.
getProperty
(
"setting"
);
if
(
setting
==
null
&&
settingNames
.
length
>
0
)
{
setting
=
settingNames
[
0
];
}
String
combobox
=
getComboBox
(
settingNames
,
setting
);
session
.
put
(
"settingsList"
,
combobox
);
ConnectionInfo
info
=
server
.
getSetting
(
setting
);
if
(
info
==
null
)
{
info
=
new
ConnectionInfo
();
}
session
.
put
(
"setting"
,
PageParser
.
escapeHtmlData
(
setting
));
session
.
put
(
"name"
,
PageParser
.
escapeHtmlData
(
setting
));
session
.
put
(
"driver"
,
PageParser
.
escapeHtmlData
(
info
.
driver
));
session
.
put
(
"url"
,
PageParser
.
escapeHtmlData
(
info
.
url
));
session
.
put
(
"user"
,
PageParser
.
escapeHtmlData
(
info
.
user
));
return
"index.jsp"
;
}
private
String
getHistory
()
{
int
id
=
Integer
.
parseInt
(
attributes
.
getProperty
(
"id"
));
String
sql
=
session
.
getCommand
(
id
);
session
.
put
(
"query"
,
PageParser
.
escapeHtmlData
(
sql
));
return
"query.jsp"
;
}
private
static
int
addColumns
(
boolean
mainSchema
,
DbTableOrView
table
,
StringBuilder
buff
,
int
treeIndex
,
boolean
showColumnTypes
,
StringBuilder
columnsBuffer
)
{
DbColumn
[]
columns
=
table
.
getColumns
();
for
(
int
i
=
0
;
columns
!=
null
&&
i
<
columns
.
length
;
i
++)
{
DbColumn
column
=
columns
[
i
];
if
(
columnsBuffer
.
length
()
>
0
)
{
columnsBuffer
.
append
(
' '
);
}
columnsBuffer
.
append
(
column
.
getName
());
String
col
=
escapeIdentifier
(
column
.
getName
());
String
level
=
mainSchema
?
", 1, 1"
:
", 2, 2"
;
buff
.
append
(
"setNode("
+
treeIndex
+
level
+
", 'column', '"
+
PageParser
.
escapeJavaScript
(
column
.
getName
())
+
"', 'javascript:ins(\\'"
+
col
+
"\\')');\n"
);
treeIndex
++;
if
(
mainSchema
&&
showColumnTypes
)
{
buff
.
append
(
"setNode("
+
treeIndex
+
", 2, 2, 'type', '"
+
PageParser
.
escapeJavaScript
(
column
.
getDataType
())
+
"', null);\n"
);
treeIndex
++;
}
}
return
treeIndex
;
}
private
static
String
escapeIdentifier
(
String
name
)
{
return
StringUtils
.
urlEncode
(
PageParser
.
escapeJavaScript
(
name
)).
replace
(
'+'
,
' '
);
}
/**
* This class represents index information for the GUI.
*/
static
class
IndexInfo
{
/**
* The index name.
*/
String
name
;
/**
* The index type name.
*/
String
type
;
/**
* The indexed columns.
*/
String
columns
;
}
private
static
int
addIndexes
(
boolean
mainSchema
,
DatabaseMetaData
meta
,
String
table
,
String
schema
,
StringBuilder
buff
,
int
treeIndex
)
throws
SQLException
{
ResultSet
rs
;
try
{
rs
=
meta
.
getIndexInfo
(
null
,
schema
,
table
,
false
,
true
);
}
catch
(
SQLException
e
)
{
// SQLite
return
treeIndex
;
}
HashMap
<
String
,
IndexInfo
>
indexMap
=
New
.
hashMap
();
while
(
rs
.
next
())
{
String
name
=
rs
.
getString
(
"INDEX_NAME"
);
IndexInfo
info
=
indexMap
.
get
(
name
);
if
(
info
==
null
)
{
int
t
=
rs
.
getInt
(
"TYPE"
);
String
type
;
if
(
t
==
DatabaseMetaData
.
tableIndexClustered
)
{
type
=
""
;
}
else
if
(
t
==
DatabaseMetaData
.
tableIndexHashed
)
{
type
=
" (${text.tree.hashed})"
;
}
else
if
(
t
==
DatabaseMetaData
.
tableIndexOther
)
{
type
=
""
;
}
else
{
type
=
null
;
}
if
(
name
!=
null
&&
type
!=
null
)
{
info
=
new
IndexInfo
();
info
.
name
=
name
;
type
=
(
rs
.
getBoolean
(
"NON_UNIQUE"
)
?
"${text.tree.nonUnique}"
:
"${text.tree.unique}"
)
+
type
;
info
.
type
=
type
;
info
.
columns
=
rs
.
getString
(
"COLUMN_NAME"
);
indexMap
.
put
(
name
,
info
);
}
}
else
{
info
.
columns
+=
", "
+
rs
.
getString
(
"COLUMN_NAME"
);
}
}
rs
.
close
();
if
(
indexMap
.
size
()
>
0
)
{
String
level
=
mainSchema
?
", 1, 1"
:
", 2, 1"
;
String
levelIndex
=
mainSchema
?
", 2, 1"
:
", 3, 1"
;
String
levelColumnType
=
mainSchema
?
", 3, 2"
:
", 4, 2"
;
buff
.
append
(
"setNode("
+
treeIndex
+
level
+
", 'index_az', '${text.tree.indexes}', null);\n"
);
treeIndex
++;
for
(
IndexInfo
info
:
indexMap
.
values
())
{
buff
.
append
(
"setNode("
+
treeIndex
+
levelIndex
+
", 'index', '"
+
PageParser
.
escapeJavaScript
(
info
.
name
)
+
"', null);\n"
);
treeIndex
++;
buff
.
append
(
"setNode("
+
treeIndex
+
levelColumnType
+
", 'type', '"
+
info
.
type
+
"', null);\n"
);
treeIndex
++;
buff
.
append
(
"setNode("
+
treeIndex
+
levelColumnType
+
", 'type', '"
+
PageParser
.
escapeJavaScript
(
info
.
columns
)
+
"', null);\n"
);
treeIndex
++;
}
}
return
treeIndex
;
}
private
int
addTablesAndViews
(
DbSchema
schema
,
boolean
mainSchema
,
StringBuilder
buff
,
int
treeIndex
)
throws
SQLException
{
if
(
schema
==
null
)
{
return
treeIndex
;
}
Connection
conn
=
session
.
getConnection
();
DatabaseMetaData
meta
=
session
.
getMetaData
();
int
level
=
mainSchema
?
0
:
1
;
boolean
showColumns
=
mainSchema
||
!
schema
.
isSystem
;
String
indentation
=
", "
+
level
+
", "
+
(
showColumns
?
"1"
:
"2"
)
+
", "
;
String
indentNode
=
", "
+
(
level
+
1
)
+
", 2, "
;
DbTableOrView
[]
tables
=
schema
.
getTables
();
if
(
tables
==
null
)
{
return
treeIndex
;
}
boolean
isOracle
=
schema
.
getContents
().
isOracle
();
boolean
notManyTables
=
tables
.
length
<
SysProperties
.
CONSOLE_MAX_TABLES_LIST_INDEXES
;
for
(
DbTableOrView
table
:
tables
)
{
if
(
table
.
isView
())
{
continue
;
}
int
tableId
=
treeIndex
;
String
tab
=
table
.
getQuotedName
();
if
(!
mainSchema
)
{
tab
=
schema
.
quotedName
+
"."
+
tab
;
}
tab
=
escapeIdentifier
(
tab
);
buff
.
append
(
"setNode("
+
treeIndex
+
indentation
+
" 'table', '"
+
PageParser
.
escapeJavaScript
(
table
.
getName
())
+
"', 'javascript:ins(\\'"
+
tab
+
"\\',true)');\n"
);
treeIndex
++;
if
(
mainSchema
||
showColumns
)
{
StringBuilder
columnsBuffer
=
new
StringBuilder
();
treeIndex
=
addColumns
(
mainSchema
,
table
,
buff
,
treeIndex
,
notManyTables
,
columnsBuffer
);
if
(!
isOracle
&&
notManyTables
)
{
treeIndex
=
addIndexes
(
mainSchema
,
meta
,
table
.
getName
(),
schema
.
name
,
buff
,
treeIndex
);
}
buff
.
append
(
"addTable('"
+
PageParser
.
escapeJavaScript
(
table
.
getName
())
+
"', '"
+
PageParser
.
escapeJavaScript
(
columnsBuffer
.
toString
())
+
"', "
+
tableId
+
");\n"
);
}
}
tables
=
schema
.
getTables
();
for
(
DbTableOrView
view
:
tables
)
{
if
(!
view
.
isView
())
{
continue
;
}
int
tableId
=
treeIndex
;
String
tab
=
view
.
getQuotedName
();
if
(!
mainSchema
)
{
tab
=
view
.
getSchema
().
quotedName
+
"."
+
tab
;
}
tab
=
escapeIdentifier
(
tab
);
buff
.
append
(
"setNode("
+
treeIndex
+
indentation
+
" 'view', '"
+
PageParser
.
escapeJavaScript
(
view
.
getName
())
+
"', 'javascript:ins(\\'"
+
tab
+
"\\',true)');\n"
);
treeIndex
++;
if
(
mainSchema
)
{
StringBuilder
columnsBuffer
=
new
StringBuilder
();
treeIndex
=
addColumns
(
mainSchema
,
view
,
buff
,
treeIndex
,
notManyTables
,
columnsBuffer
);
if
(
schema
.
getContents
().
isH2
())
{
try
(
PreparedStatement
prep
=
conn
.
prepareStatement
(
"SELECT * FROM "
+
"INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME=?"
))
{
prep
.
setString
(
1
,
view
.
getName
());
ResultSet
rs
=
prep
.
executeQuery
();
if
(
rs
.
next
())
{
String
sql
=
rs
.
getString
(
"SQL"
);
buff
.
append
(
"setNode("
+
treeIndex
+
indentNode
+
" 'type', '"
+
PageParser
.
escapeJavaScript
(
sql
)
+
"', null);\n"
);
treeIndex
++;
}
rs
.
close
();
}
}
buff
.
append
(
"addTable('"
+
PageParser
.
escapeJavaScript
(
view
.
getName
())
+
"', '"
+
PageParser
.
escapeJavaScript
(
columnsBuffer
.
toString
())
+
"', "
+
tableId
+
");\n"
);
}
}
return
treeIndex
;
}
private
String
tables
()
{
DbContents
contents
=
session
.
getContents
();
boolean
isH2
=
false
;
try
{
String
url
=
(
String
)
session
.
get
(
"url"
);
Connection
conn
=
session
.
getConnection
();
contents
.
readContents
(
url
,
conn
);
session
.
loadBnf
();
isH2
=
contents
.
isH2
();
StringBuilder
buff
=
new
StringBuilder
();
buff
.
append
(
"setNode(0, 0, 0, 'database', '"
+
PageParser
.
escapeJavaScript
(
url
)
+
"', null);\n"
);
int
treeIndex
=
1
;
DbSchema
defaultSchema
=
contents
.
getDefaultSchema
();
treeIndex
=
addTablesAndViews
(
defaultSchema
,
true
,
buff
,
treeIndex
);
DbSchema
[]
schemas
=
contents
.
getSchemas
();
for
(
DbSchema
schema
:
schemas
)
{
if
(
schema
==
defaultSchema
||
schema
==
null
)
{
continue
;
}
buff
.
append
(
"setNode("
+
treeIndex
+
", 0, 1, 'folder', '"
+
PageParser
.
escapeJavaScript
(
schema
.
name
)
+
"', null);\n"
);
treeIndex
++;
treeIndex
=
addTablesAndViews
(
schema
,
false
,
buff
,
treeIndex
);
}
if
(
isH2
)
{
try
(
Statement
stat
=
conn
.
createStatement
())
{
ResultSet
rs
=
stat
.
executeQuery
(
"SELECT * FROM "
+
"INFORMATION_SCHEMA.SEQUENCES ORDER BY SEQUENCE_NAME"
);
for
(
int
i
=
0
;
rs
.
next
();
i
++)
{
if
(
i
==
0
)
{
buff
.
append
(
"setNode("
+
treeIndex
+
", 0, 1, 'sequences', '${text.tree.sequences}', null);\n"
);
treeIndex
++;
}
String
name
=
rs
.
getString
(
"SEQUENCE_NAME"
);
String
current
=
rs
.
getString
(
"CURRENT_VALUE"
);
String
increment
=
rs
.
getString
(
"INCREMENT"
);
buff
.
append
(
"setNode("
+
treeIndex
+
", 1, 1, 'sequence', '"
+
PageParser
.
escapeJavaScript
(
name
)
+
"', null);\n"
);
treeIndex
++;
buff
.
append
(
"setNode("
+
treeIndex
+
", 2, 2, 'type', '${text.tree.current}: "
+
PageParser
.
escapeJavaScript
(
current
)
+
"', null);\n"
);
treeIndex
++;
if
(!
"1"
.
equals
(
increment
))
{
buff
.
append
(
"setNode("
+
treeIndex
+
", 2, 2, 'type', '${text.tree.increment}: "
+
PageParser
.
escapeJavaScript
(
increment
)
+
"', null);\n"
);
treeIndex
++;
}
}
rs
.
close
();
rs
=
stat
.
executeQuery
(
"SELECT * FROM "
+
"INFORMATION_SCHEMA.USERS ORDER BY NAME"
);
for
(
int
i
=
0
;
rs
.
next
();
i
++)
{
if
(
i
==
0
)
{
buff
.
append
(
"setNode("
+
treeIndex
+
", 0, 1, 'users', '${text.tree.users}', null);\n"
);
treeIndex
++;
}
String
name
=
rs
.
getString
(
"NAME"
);
String
admin
=
rs
.
getString
(
"ADMIN"
);
buff
.
append
(
"setNode("
+
treeIndex
+
", 1, 1, 'user', '"
+
PageParser
.
escapeJavaScript
(
name
)
+
"', null);\n"
);
treeIndex
++;
if
(
admin
.
equalsIgnoreCase
(
"TRUE"
))
{
buff
.
append
(
"setNode("
+
treeIndex
+
", 2, 2, 'type', '${text.tree.admin}', null);\n"
);
treeIndex
++;
}
}
rs
.
close
();
}
}
DatabaseMetaData
meta
=
session
.
getMetaData
();
String
version
=
meta
.
getDatabaseProductName
()
+
" "
+
meta
.
getDatabaseProductVersion
();
buff
.
append
(
"setNode("
+
treeIndex
+
", 0, 0, 'info', '"
+
PageParser
.
escapeJavaScript
(
version
)
+
"', null);\n"
);
buff
.
append
(
"refreshQueryTables();"
);
session
.
put
(
"tree"
,
buff
.
toString
());
}
catch
(
Exception
e
)
{
session
.
put
(
"tree"
,
""
);
session
.
put
(
"error"
,
getStackTrace
(
0
,
e
,
isH2
));
}
return
"tables.jsp"
;
}
private
String
getStackTrace
(
int
id
,
Throwable
e
,
boolean
isH2
)
{
try
{
StringWriter
writer
=
new
StringWriter
();
e
.
printStackTrace
(
new
PrintWriter
(
writer
));
String
stackTrace
=
writer
.
toString
();
stackTrace
=
PageParser
.
escapeHtml
(
stackTrace
);
if
(
isH2
)
{
stackTrace
=
linkToSource
(
stackTrace
);
}
stackTrace
=
StringUtils
.
replaceAll
(
stackTrace
,
"\t"
,
" "
);
String
message
=
PageParser
.
escapeHtml
(
e
.
getMessage
());
String
error
=
"<a class=\"error\" href=\"#\" "
+
"onclick=\"var x=document.getElementById('st"
+
id
+
"').style;x.display=x.display==''?'none':'';\">"
+
message
+
"</a>"
;
if
(
e
instanceof
SQLException
)
{
SQLException
se
=
(
SQLException
)
e
;
error
+=
" "
+
se
.
getSQLState
()
+
"/"
+
se
.
getErrorCode
();
if
(
isH2
)
{
int
code
=
se
.
getErrorCode
();
error
+=
" <a href=\"http://h2database.com/javadoc/"
+
"org/h2/api/ErrorCode.html#c"
+
code
+
"\">(${text.a.help})</a>"
;
}
}
error
+=
"<span style=\"display: none;\" id=\"st"
+
id
+
"\"><br />"
+
stackTrace
+
"</span>"
;
error
=
formatAsError
(
error
);
return
error
;
}
catch
(
OutOfMemoryError
e2
)
{
server
.
traceError
(
e
);
return
e
.
toString
();
}
}
private
static
String
linkToSource
(
String
s
)
{
try
{
StringBuilder
result
=
new
StringBuilder
(
s
.
length
());
int
idx
=
s
.
indexOf
(
"<br />"
);
result
.
append
(
s
.
substring
(
0
,
idx
));
while
(
true
)
{
int
start
=
s
.
indexOf
(
"org.h2."
,
idx
);
if
(
start
<
0
)
{
result
.
append
(
s
.
substring
(
idx
));
break
;
}
result
.
append
(
s
.
substring
(
idx
,
start
));
int
end
=
s
.
indexOf
(
')'
,
start
);
if
(
end
<
0
)
{
result
.
append
(
s
.
substring
(
idx
));
break
;
}
String
element
=
s
.
substring
(
start
,
end
);
int
open
=
element
.
lastIndexOf
(
'('
);
int
dotMethod
=
element
.
lastIndexOf
(
'.'
,
open
-
1
);
int
dotClass
=
element
.
lastIndexOf
(
'.'
,
dotMethod
-
1
);
String
packageName
=
element
.
substring
(
0
,
dotClass
);
int
colon
=
element
.
lastIndexOf
(
':'
);
String
file
=
element
.
substring
(
open
+
1
,
colon
);
String
lineNumber
=
element
.
substring
(
colon
+
1
,
element
.
length
());
String
fullFileName
=
packageName
.
replace
(
'.'
,
'/'
)
+
"/"
+
file
;
result
.
append
(
"<a href=\"http://h2database.com/html/source.html?file="
);
result
.
append
(
fullFileName
);
result
.
append
(
"&line="
);
result
.
append
(
lineNumber
);
result
.
append
(
"&build="
);
result
.
append
(
Constants
.
BUILD_ID
);
result
.
append
(
"\">"
);
result
.
append
(
element
);
result
.
append
(
"</a>"
);
idx
=
end
;
}
return
result
.
toString
();
}
catch
(
Throwable
t
)
{
return
s
;
}
}
private
static
String
formatAsError
(
String
s
)
{
return
"<div class=\"error\">"
+
s
+
"</div>"
;
}
private
String
test
()
{
String
driver
=
attributes
.
getProperty
(
"driver"
,
""
);
String
url
=
attributes
.
getProperty
(
"url"
,
""
);
String
user
=
attributes
.
getProperty
(
"user"
,
""
);
String
password
=
attributes
.
getProperty
(
"password"
,
""
);
session
.
put
(
"driver"
,
driver
);
session
.
put
(
"url"
,
url
);
session
.
put
(
"user"
,
user
);
boolean
isH2
=
url
.
startsWith
(
"jdbc:h2:"
);
try
{
long
start
=
System
.
currentTimeMillis
();
String
profOpen
=
""
,
profClose
=
""
;
Profiler
prof
=
new
Profiler
();
prof
.
startCollecting
();
Connection
conn
;
try
{
conn
=
server
.
getConnection
(
driver
,
url
,
user
,
password
);
}
finally
{
prof
.
stopCollecting
();
profOpen
=
prof
.
getTop
(
3
);
}
prof
=
new
Profiler
();
prof
.
startCollecting
();
try
{
JdbcUtils
.
closeSilently
(
conn
);
}
finally
{
prof
.
stopCollecting
();
profClose
=
prof
.
getTop
(
3
);
}
long
time
=
System
.
currentTimeMillis
()
-
start
;
String
success
;
if
(
time
>
1000
)
{
success
=
"<a class=\"error\" href=\"#\" "
+
"onclick=\"var x=document.getElementById('prof').style;x."
+
"display=x.display==''?'none':'';\">"
+
"${text.login.testSuccessful}</a>"
+
"<span style=\"display: none;\" id=\"prof\"><br />"
+
PageParser
.
escapeHtml
(
profOpen
)
+
"<br />"
+
PageParser
.
escapeHtml
(
profClose
)
+
"</span>"
;
}
else
{
success
=
"${text.login.testSuccessful}"
;
}
session
.
put
(
"error"
,
success
);
// session.put("error", "${text.login.testSuccessful}");
return
"login.jsp"
;
}
catch
(
Exception
e
)
{
session
.
put
(
"error"
,
getLoginError
(
e
,
isH2
));
return
"login.jsp"
;
}
}
/**
* Get the formatted login error message.
*
* @param e the exception
* @param isH2 if the current database is a H2 database
* @return the formatted error message
*/
private
String
getLoginError
(
Exception
e
,
boolean
isH2
)
{
if
(
e
instanceof
JdbcSQLException
&&
((
JdbcSQLException
)
e
).
getErrorCode
()
==
ErrorCode
.
CLASS_NOT_FOUND_1
)
{
return
"${text.login.driverNotFound}<br />"
+
getStackTrace
(
0
,
e
,
isH2
);
}
return
getStackTrace
(
0
,
e
,
isH2
);
}
private
String
login
()
{
String
driver
=
attributes
.
getProperty
(
"driver"
,
""
);
String
url
=
attributes
.
getProperty
(
"url"
,
""
);
String
user
=
attributes
.
getProperty
(
"user"
,
""
);
String
password
=
attributes
.
getProperty
(
"password"
,
""
);
session
.
put
(
"autoCommit"
,
"checked"
);
session
.
put
(
"autoComplete"
,
"1"
);
session
.
put
(
"maxrows"
,
"1000"
);
boolean
isH2
=
url
.
startsWith
(
"jdbc:h2:"
);
try
{
Connection
conn
=
server
.
getConnection
(
driver
,
url
,
user
,
password
);
session
.
setConnection
(
conn
);
session
.
put
(
"url"
,
url
);
session
.
put
(
"user"
,
user
);
session
.
remove
(
"error"
);
settingSave
();
return
"frame.jsp"
;
}
catch
(
Exception
e
)
{
session
.
put
(
"error"
,
getLoginError
(
e
,
isH2
));
return
"login.jsp"
;
}
}
private
String
logout
()
{
try
{
Connection
conn
=
session
.
getConnection
();
session
.
setConnection
(
null
);
session
.
remove
(
"conn"
);
session
.
remove
(
"result"
);
session
.
remove
(
"tables"
);
session
.
remove
(
"user"
);
session
.
remove
(
"tool"
);
if
(
conn
!=
null
)
{
if
(
session
.
getShutdownServerOnDisconnect
())
{
server
.
shutdown
();
}
else
{
conn
.
close
();
}
}
}
catch
(
Exception
e
)
{
trace
(
e
.
toString
());
}
return
"index.do"
;
}
private
String
query
()
{
String
sql
=
attributes
.
getProperty
(
"sql"
).
trim
();
try
{
ScriptReader
r
=
new
ScriptReader
(
new
StringReader
(
sql
));
final
ArrayList
<
String
>
list
=
New
.
arrayList
();
while
(
true
)
{
String
s
=
r
.
readStatement
();
if
(
s
==
null
)
{
break
;
}
list
.
add
(
s
);
}
final
Connection
conn
=
session
.
getConnection
();
if
(
SysProperties
.
CONSOLE_STREAM
&&
server
.
getAllowChunked
())
{
String
page
=
new
String
(
server
.
getFile
(
"result.jsp"
),
Constants
.
UTF8
);
int
idx
=
page
.
indexOf
(
"${result}"
);
// the first element of the list is the header, the last the
// footer
list
.
add
(
0
,
page
.
substring
(
0
,
idx
));
list
.
add
(
page
.
substring
(
idx
+
"${result}"
.
length
()));
session
.
put
(
"chunks"
,
new
Iterator
<
String
>()
{
private
int
i
;
@Override
public
boolean
hasNext
()
{
return
i
<
list
.
size
();
}
@Override
public
String
next
()
{
String
s
=
list
.
get
(
i
++);
if
(
i
==
1
||
i
==
list
.
size
())
{
return
s
;
}
StringBuilder
b
=
new
StringBuilder
();
query
(
conn
,
s
,
i
-
1
,
list
.
size
()
-
2
,
b
);
return
b
.
toString
();
}
@Override
public
void
remove
()
{
throw
new
UnsupportedOperationException
();
}
});
return
"result.jsp"
;
}
String
result
;
StringBuilder
buff
=
new
StringBuilder
();
for
(
int
i
=
0
;
i
<
list
.
size
();
i
++)
{
String
s
=
list
.
get
(
i
);
query
(
conn
,
s
,
i
,
list
.
size
(),
buff
);
}
result
=
buff
.
toString
();
session
.
put
(
"result"
,
result
);
}
catch
(
Throwable
e
)
{
session
.
put
(
"result"
,
getStackTrace
(
0
,
e
,
session
.
getContents
().
isH2
()));
}
return
"result.jsp"
;
}
/**
* Execute a query and append the result to the buffer.
*
* @param conn the connection
* @param s the statement
* @param i the index
* @param size the number of statements
* @param buff the target buffer
*/
void
query
(
Connection
conn
,
String
s
,
int
i
,
int
size
,
StringBuilder
buff
)
{
if
(!(
s
.
startsWith
(
"@"
)
&&
s
.
endsWith
(
"."
)))
{
buff
.
append
(
PageParser
.
escapeHtml
(
s
+
";"
)).
append
(
"<br />"
);
}
boolean
forceEdit
=
s
.
startsWith
(
"@edit"
);
buff
.
append
(
getResult
(
conn
,
i
+
1
,
s
,
size
==
1
,
forceEdit
)).
append
(
"<br />"
);
}
private
String
editResult
()
{
ResultSet
rs
=
session
.
result
;
int
row
=
Integer
.
parseInt
(
attributes
.
getProperty
(
"row"
));
int
op
=
Integer
.
parseInt
(
attributes
.
getProperty
(
"op"
));
String
result
=
""
,
error
=
""
;
try
{
if
(
op
==
1
)
{
boolean
insert
=
row
<
0
;
if
(
insert
)
{
rs
.
moveToInsertRow
();
}
else
{
rs
.
absolute
(
row
);
}
for
(
int
i
=
0
;
i
<
rs
.
getMetaData
().
getColumnCount
();
i
++)
{
String
x
=
attributes
.
getProperty
(
"r"
+
row
+
"c"
+
(
i
+
1
));
unescapeData
(
x
,
rs
,
i
+
1
);
}
if
(
insert
)
{
rs
.
insertRow
();
}
else
{
rs
.
updateRow
();
}
}
else
if
(
op
==
2
)
{
rs
.
absolute
(
row
);
rs
.
deleteRow
();
}
else
if
(
op
==
3
)
{
// cancel
}
}
catch
(
Throwable
e
)
{
result
=
"<br />"
+
getStackTrace
(
0
,
e
,
session
.
getContents
().
isH2
());
error
=
formatAsError
(
e
.
getMessage
());
}
String
sql
=
"@edit "
+
(
String
)
session
.
get
(
"resultSetSQL"
);
Connection
conn
=
session
.
getConnection
();
result
=
error
+
getResult
(
conn
,
-
1
,
sql
,
true
,
true
)
+
result
;
session
.
put
(
"result"
,
result
);
return
"result.jsp"
;
}
private
ResultSet
getMetaResultSet
(
Connection
conn
,
String
sql
)
throws
SQLException
{
DatabaseMetaData
meta
=
conn
.
getMetaData
();
if
(
isBuiltIn
(
sql
,
"@best_row_identifier"
))
{
String
[]
p
=
split
(
sql
);
int
scale
=
p
[
4
]
==
null
?
0
:
Integer
.
parseInt
(
p
[
4
]);
boolean
nullable
=
p
[
5
]
==
null
?
false
:
Boolean
.
parseBoolean
(
p
[
5
]);
return
meta
.
getBestRowIdentifier
(
p
[
1
],
p
[
2
],
p
[
3
],
scale
,
nullable
);
}
else
if
(
isBuiltIn
(
sql
,
"@catalogs"
))
{
return
meta
.
getCatalogs
();
}
else
if
(
isBuiltIn
(
sql
,
"@columns"
))
{
String
[]
p
=
split
(
sql
);
return
meta
.
getColumns
(
p
[
1
],
p
[
2
],
p
[
3
],
p
[
4
]);
}
else
if
(
isBuiltIn
(
sql
,
"@column_privileges"
))
{
String
[]
p
=
split
(
sql
);
return
meta
.
getColumnPrivileges
(
p
[
1
],
p
[
2
],
p
[
3
],
p
[
4
]);
}
else
if
(
isBuiltIn
(
sql
,
"@cross_references"
))
{
String
[]
p
=
split
(
sql
);
return
meta
.
getCrossReference
(
p
[
1
],
p
[
2
],
p
[
3
],
p
[
4
],
p
[
5
],
p
[
6
]);
}
else
if
(
isBuiltIn
(
sql
,
"@exported_keys"
))
{
String
[]
p
=
split
(
sql
);
return
meta
.
getExportedKeys
(
p
[
1
],
p
[
2
],
p
[
3
]);
}
else
if
(
isBuiltIn
(
sql
,
"@imported_keys"
))
{
String
[]
p
=
split
(
sql
);
return
meta
.
getImportedKeys
(
p
[
1
],
p
[
2
],
p
[
3
]);
}
else
if
(
isBuiltIn
(
sql
,
"@index_info"
))
{
String
[]
p
=
split
(
sql
);
boolean
unique
=
p
[
4
]
==
null
?
false
:
Boolean
.
parseBoolean
(
p
[
4
]);
boolean
approx
=
p
[
5
]
==
null
?
false
:
Boolean
.
parseBoolean
(
p
[
5
]);
return
meta
.
getIndexInfo
(
p
[
1
],
p
[
2
],
p
[
3
],
unique
,
approx
);
}
else
if
(
isBuiltIn
(
sql
,
"@primary_keys"
))
{
String
[]
p
=
split
(
sql
);
return
meta
.
getPrimaryKeys
(
p
[
1
],
p
[
2
],
p
[
3
]);
}
else
if
(
isBuiltIn
(
sql
,
"@procedures"
))
{
String
[]
p
=
split
(
sql
);
return
meta
.
getProcedures
(
p
[
1
],
p
[
2
],
p
[
3
]);
}
else
if
(
isBuiltIn
(
sql
,
"@procedure_columns"
))
{
String
[]
p
=
split
(
sql
);
return
meta
.
getProcedureColumns
(
p
[
1
],
p
[
2
],
p
[
3
],
p
[
4
]);
}
else
if
(
isBuiltIn
(
sql
,
"@schemas"
))
{
return
meta
.
getSchemas
();
}
else
if
(
isBuiltIn
(
sql
,
"@tables"
))
{
String
[]
p
=
split
(
sql
);
String
[]
types
=
p
[
4
]
==
null
?
null
:
StringUtils
.
arraySplit
(
p
[
4
],
','
,
false
);
return
meta
.
getTables
(
p
[
1
],
p
[
2
],
p
[
3
],
types
);
}
else
if
(
isBuiltIn
(
sql
,
"@table_privileges"
))
{
String
[]
p
=
split
(
sql
);
return
meta
.
getTablePrivileges
(
p
[
1
],
p
[
2
],
p
[
3
]);
}
else
if
(
isBuiltIn
(
sql
,
"@table_types"
))
{
return
meta
.
getTableTypes
();
}
else
if
(
isBuiltIn
(
sql
,
"@type_info"
))
{
return
meta
.
getTypeInfo
();
}
else
if
(
isBuiltIn
(
sql
,
"@udts"
))
{
String
[]
p
=
split
(
sql
);
int
[]
types
;
if
(
p
[
4
]
==
null
)
{
types
=
null
;
}
else
{
String
[]
t
=
StringUtils
.
arraySplit
(
p
[
4
],
','
,
false
);
types
=
new
int
[
t
.
length
];
for
(
int
i
=
0
;
i
<
t
.
length
;
i
++)
{
types
[
i
]
=
Integer
.
parseInt
(
t
[
i
]);
}
}
return
meta
.
getUDTs
(
p
[
1
],
p
[
2
],
p
[
3
],
types
);
}
else
if
(
isBuiltIn
(
sql
,
"@version_columns"
))
{
String
[]
p
=
split
(
sql
);
return
meta
.
getVersionColumns
(
p
[
1
],
p
[
2
],
p
[
3
]);
}
else
if
(
isBuiltIn
(
sql
,
"@memory"
))
{
SimpleResultSet
rs
=
new
SimpleResultSet
();
rs
.
addColumn
(
"Type"
,
Types
.
VARCHAR
,
0
,
0
);
rs
.
addColumn
(
"KB"
,
Types
.
VARCHAR
,
0
,
0
);
rs
.
addRow
(
"Used Memory"
,
""
+
Utils
.
getMemoryUsed
());
rs
.
addRow
(
"Free Memory"
,
""
+
Utils
.
getMemoryFree
());
return
rs
;
}
else
if
(
isBuiltIn
(
sql
,
"@info"
))
{
SimpleResultSet
rs
=
new
SimpleResultSet
();
rs
.
addColumn
(
"KEY"
,
Types
.
VARCHAR
,
0
,
0
);
rs
.
addColumn
(
"VALUE"
,
Types
.
VARCHAR
,
0
,
0
);
rs
.
addRow
(
"conn.getCatalog"
,
conn
.
getCatalog
());
rs
.
addRow
(
"conn.getAutoCommit"
,
""
+
conn
.
getAutoCommit
());
rs
.
addRow
(
"conn.getTransactionIsolation"
,
""
+
conn
.
getTransactionIsolation
());
rs
.
addRow
(
"conn.getWarnings"
,
""
+
conn
.
getWarnings
());
String
map
;
try
{
map
=
""
+
conn
.
getTypeMap
();
}
catch
(
SQLException
e
)
{
map
=
e
.
toString
();
}
rs
.
addRow
(
"conn.getTypeMap"
,
""
+
map
);
rs
.
addRow
(
"conn.isReadOnly"
,
""
+
conn
.
isReadOnly
());
rs
.
addRow
(
"conn.getHoldability"
,
""
+
conn
.
getHoldability
());
addDatabaseMetaData
(
rs
,
meta
);
return
rs
;
}
else
if
(
isBuiltIn
(
sql
,
"@attributes"
))
{
String
[]
p
=
split
(
sql
);
return
meta
.
getAttributes
(
p
[
1
],
p
[
2
],
p
[
3
],
p
[
4
]);
}
else
if
(
isBuiltIn
(
sql
,
"@super_tables"
))
{
String
[]
p
=
split
(
sql
);
return
meta
.
getSuperTables
(
p
[
1
],
p
[
2
],
p
[
3
]);
}
else
if
(
isBuiltIn
(
sql
,
"@super_types"
))
{
String
[]
p
=
split
(
sql
);
return
meta
.
getSuperTypes
(
p
[
1
],
p
[
2
],
p
[
3
]);
}
else
if
(
isBuiltIn
(
sql
,
"@prof_stop"
))
{
if
(
profiler
!=
null
)
{
profiler
.
stopCollecting
();
SimpleResultSet
rs
=
new
SimpleResultSet
();
rs
.
addColumn
(
"Top Stack Trace(s)"
,
Types
.
VARCHAR
,
0
,
0
);
rs
.
addRow
(
profiler
.
getTop
(
3
));
profiler
=
null
;
return
rs
;
}
}
return
null
;
}
private
static
void
addDatabaseMetaData
(
SimpleResultSet
rs
,
DatabaseMetaData
meta
)
{
Method
[]
methods
=
DatabaseMetaData
.
class
.
getDeclaredMethods
();
Arrays
.
sort
(
methods
,
new
Comparator
<
Method
>()
{
@Override
public
int
compare
(
Method
o1
,
Method
o2
)
{
return
o1
.
toString
().
compareTo
(
o2
.
toString
());
}
});
for
(
Method
m
:
methods
)
{
if
(
m
.
getParameterTypes
().
length
==
0
)
{
try
{
Object
o
=
m
.
invoke
(
meta
);
rs
.
addRow
(
"meta."
+
m
.
getName
(),
""
+
o
);
}
catch
(
InvocationTargetException
e
)
{
rs
.
addRow
(
"meta."
+
m
.
getName
(),
e
.
getTargetException
().
toString
());
}
catch
(
Exception
e
)
{
rs
.
addRow
(
"meta."
+
m
.
getName
(),
e
.
toString
());
}
}
}
}
private
static
String
[]
split
(
String
s
)
{
String
[]
list
=
new
String
[
10
];
String
[]
t
=
StringUtils
.
arraySplit
(
s
,
' '
,
true
);
System
.
arraycopy
(
t
,
0
,
list
,
0
,
t
.
length
);
for
(
int
i
=
0
;
i
<
list
.
length
;
i
++)
{
if
(
"null"
.
equals
(
list
[
i
]))
{
list
[
i
]
=
null
;
}
}
return
list
;
}
private
int
getMaxrows
()
{
String
r
=
(
String
)
session
.
get
(
"maxrows"
);
int
maxrows
=
r
==
null
?
0
:
Integer
.
parseInt
(
r
);
return
maxrows
;
}
private
String
getResult
(
Connection
conn
,
int
id
,
String
sql
,
boolean
allowEdit
,
boolean
forceEdit
)
{
try
{
sql
=
sql
.
trim
();
StringBuilder
buff
=
new
StringBuilder
();
String
sqlUpper
=
StringUtils
.
toUpperEnglish
(
sql
);
if
(
sqlUpper
.
contains
(
"CREATE"
)
||
sqlUpper
.
contains
(
"DROP"
)
||
sqlUpper
.
contains
(
"ALTER"
)
||
sqlUpper
.
contains
(
"RUNSCRIPT"
))
{
String
sessionId
=
attributes
.
getProperty
(
"jsessionid"
);
buff
.
append
(
"<script type=\"text/javascript\">"
+
"parent['h2menu'].location='tables.do?jsessionid="
+
sessionId
+
"';</script>"
);
}
Statement
stat
;
DbContents
contents
=
session
.
getContents
();
if
(
forceEdit
||
(
allowEdit
&&
contents
.
isH2
()))
{
stat
=
conn
.
createStatement
(
ResultSet
.
TYPE_SCROLL_INSENSITIVE
,
ResultSet
.
CONCUR_UPDATABLE
);
}
else
{
stat
=
conn
.
createStatement
();
}
ResultSet
rs
;
long
time
=
System
.
currentTimeMillis
();
boolean
metadata
=
false
;
boolean
generatedKeys
=
false
;
boolean
edit
=
false
;
boolean
list
=
false
;
if
(
isBuiltIn
(
sql
,
"@autocommit_true"
))
{
conn
.
setAutoCommit
(
true
);
return
"${text.result.autoCommitOn}"
;
}
else
if
(
isBuiltIn
(
sql
,
"@autocommit_false"
))
{
conn
.
setAutoCommit
(
false
);
return
"${text.result.autoCommitOff}"
;
}
else
if
(
isBuiltIn
(
sql
,
"@cancel"
))
{
stat
=
session
.
executingStatement
;
if
(
stat
!=
null
)
{
stat
.
cancel
();
buff
.
append
(
"${text.result.statementWasCanceled}"
);
}
else
{
buff
.
append
(
"${text.result.noRunningStatement}"
);
}
return
buff
.
toString
();
}
else
if
(
isBuiltIn
(
sql
,
"@edit"
))
{
edit
=
true
;
sql
=
sql
.
substring
(
"@edit"
.
length
()).
trim
();
session
.
put
(
"resultSetSQL"
,
sql
);
}
if
(
isBuiltIn
(
sql
,
"@list"
))
{
list
=
true
;
sql
=
sql
.
substring
(
"@list"
.
length
()).
trim
();
}
if
(
isBuiltIn
(
sql
,
"@meta"
))
{
metadata
=
true
;
sql
=
sql
.
substring
(
"@meta"
.
length
()).
trim
();
}
if
(
isBuiltIn
(
sql
,
"@generated"
))
{
generatedKeys
=
true
;
sql
=
sql
.
substring
(
"@generated"
.
length
()).
trim
();
}
else
if
(
isBuiltIn
(
sql
,
"@history"
))
{
buff
.
append
(
getCommandHistoryString
());
return
buff
.
toString
();
}
else
if
(
isBuiltIn
(
sql
,
"@loop"
))
{
sql
=
sql
.
substring
(
"@loop"
.
length
()).
trim
();
int
idx
=
sql
.
indexOf
(
' '
);
int
count
=
Integer
.
decode
(
sql
.
substring
(
0
,
idx
));
sql
=
sql
.
substring
(
idx
).
trim
();
return
executeLoop
(
conn
,
count
,
sql
);
}
else
if
(
isBuiltIn
(
sql
,
"@maxrows"
))
{
int
maxrows
=
(
int
)
Double
.
parseDouble
(
sql
.
substring
(
"@maxrows"
.
length
()).
trim
());
session
.
put
(
"maxrows"
,
""
+
maxrows
);
return
"${text.result.maxrowsSet}"
;
}
else
if
(
isBuiltIn
(
sql
,
"@parameter_meta"
))
{
sql
=
sql
.
substring
(
"@parameter_meta"
.
length
()).
trim
();
PreparedStatement
prep
=
conn
.
prepareStatement
(
sql
);
buff
.
append
(
getParameterResultSet
(
prep
.
getParameterMetaData
()));
return
buff
.
toString
();
}
else
if
(
isBuiltIn
(
sql
,
"@password_hash"
))
{
sql
=
sql
.
substring
(
"@password_hash"
.
length
()).
trim
();
String
[]
p
=
split
(
sql
);
return
StringUtils
.
convertBytesToHex
(
SHA256
.
getKeyPasswordHash
(
p
[
0
],
p
[
1
].
toCharArray
()));
}
else
if
(
isBuiltIn
(
sql
,
"@prof_start"
))
{
if
(
profiler
!=
null
)
{
profiler
.
stopCollecting
();
}
profiler
=
new
Profiler
();
profiler
.
startCollecting
();
return
"Ok"
;
}
else
if
(
isBuiltIn
(
sql
,
"@sleep"
))
{
String
s
=
sql
.
substring
(
"@sleep"
.
length
()).
trim
();
int
sleep
=
1
;
if
(
s
.
length
()
>
0
)
{
sleep
=
Integer
.
parseInt
(
s
);
}
Thread
.
sleep
(
sleep
*
1000
);
return
"Ok"
;
}
else
if
(
isBuiltIn
(
sql
,
"@transaction_isolation"
))
{
String
s
=
sql
.
substring
(
"@transaction_isolation"
.
length
()).
trim
();
if
(
s
.
length
()
>
0
)
{
int
level
=
Integer
.
parseInt
(
s
);
conn
.
setTransactionIsolation
(
level
);
}
buff
.
append
(
"Transaction Isolation: "
+
conn
.
getTransactionIsolation
()
+
"<br />"
);
buff
.
append
(
Connection
.
TRANSACTION_READ_UNCOMMITTED
+
": read_uncommitted<br />"
);
buff
.
append
(
Connection
.
TRANSACTION_READ_COMMITTED
+
": read_committed<br />"
);
buff
.
append
(
Connection
.
TRANSACTION_REPEATABLE_READ
+
": repeatable_read<br />"
);
buff
.
append
(
Connection
.
TRANSACTION_SERIALIZABLE
+
": serializable"
);
}
if
(
sql
.
startsWith
(
"@"
))
{
rs
=
getMetaResultSet
(
conn
,
sql
);
if
(
rs
==
null
)
{
buff
.
append
(
"?: "
+
sql
);
return
buff
.
toString
();
}
}
else
{
int
maxrows
=
getMaxrows
();
stat
.
setMaxRows
(
maxrows
);
session
.
executingStatement
=
stat
;
boolean
isResultSet
=
stat
.
execute
(
sql
);
session
.
addCommand
(
sql
);
if
(
generatedKeys
)
{
rs
=
null
;
rs
=
stat
.
getGeneratedKeys
();
}
else
{
if
(!
isResultSet
)
{
buff
.
append
(
"${text.result.updateCount}: "
+
stat
.
getUpdateCount
());
time
=
System
.
currentTimeMillis
()
-
time
;
buff
.
append
(
"<br />("
).
append
(
time
).
append
(
" ms)"
);
stat
.
close
();
return
buff
.
toString
();
}
rs
=
stat
.
getResultSet
();
}
}
time
=
System
.
currentTimeMillis
()
-
time
;
buff
.
append
(
getResultSet
(
sql
,
rs
,
metadata
,
list
,
edit
,
time
,
allowEdit
));
// SQLWarning warning = stat.getWarnings();
// if (warning != null) {
// buff.append("<br />Warning:<br />").
// append(getStackTrace(id, warning));
// }
if
(!
edit
)
{
stat
.
close
();
}
return
buff
.
toString
();
}
catch
(
Throwable
e
)
{
// throwable: including OutOfMemoryError and so on
return
getStackTrace
(
id
,
e
,
session
.
getContents
().
isH2
());
}
finally
{
session
.
executingStatement
=
null
;
}
}
private
static
boolean
isBuiltIn
(
String
sql
,
String
builtIn
)
{
return
StringUtils
.
startsWithIgnoreCase
(
sql
,
builtIn
);
}
private
String
executeLoop
(
Connection
conn
,
int
count
,
String
sql
)
throws
SQLException
{
ArrayList
<
Integer
>
params
=
New
.
arrayList
();
int
idx
=
0
;
while
(!
stop
)
{
idx
=
sql
.
indexOf
(
'?'
,
idx
);
if
(
idx
<
0
)
{
break
;
}
if
(
isBuiltIn
(
sql
.
substring
(
idx
),
"?/*rnd*/"
))
{
params
.
add
(
1
);
sql
=
sql
.
substring
(
0
,
idx
)
+
"?"
+
sql
.
substring
(
idx
+
"/*rnd*/"
.
length
()
+
1
);
}
else
{
params
.
add
(
0
);
}
idx
++;
}
boolean
prepared
;
Random
random
=
new
Random
(
1
);
long
time
=
System
.
currentTimeMillis
();
if
(
isBuiltIn
(
sql
,
"@statement"
))
{
sql
=
sql
.
substring
(
"@statement"
.
length
()).
trim
();
prepared
=
false
;
Statement
stat
=
conn
.
createStatement
();
for
(
int
i
=
0
;
!
stop
&&
i
<
count
;
i
++)
{
String
s
=
sql
;
for
(
Integer
type
:
params
)
{
idx
=
s
.
indexOf
(
'?'
);
if
(
type
.
intValue
()
==
1
)
{
s
=
s
.
substring
(
0
,
idx
)
+
random
.
nextInt
(
count
)
+
s
.
substring
(
idx
+
1
);
}
else
{
s
=
s
.
substring
(
0
,
idx
)
+
i
+
s
.
substring
(
idx
+
1
);
}
}
if
(
stat
.
execute
(
s
))
{
ResultSet
rs
=
stat
.
getResultSet
();
while
(!
stop
&&
rs
.
next
())
{
// maybe get the data as well
}
rs
.
close
();
}
}
}
else
{
prepared
=
true
;
PreparedStatement
prep
=
conn
.
prepareStatement
(
sql
);
for
(
int
i
=
0
;
!
stop
&&
i
<
count
;
i
++)
{
for
(
int
j
=
0
;
j
<
params
.
size
();
j
++)
{
Integer
type
=
params
.
get
(
j
);
if
(
type
.
intValue
()
==
1
)
{
prep
.
setInt
(
j
+
1
,
random
.
nextInt
(
count
));
}
else
{
prep
.
setInt
(
j
+
1
,
i
);
}
}
if
(
session
.
getContents
().
isSQLite
())
{
// SQLite currently throws an exception on prep.execute()
prep
.
executeUpdate
();
}
else
{
if
(
prep
.
execute
())
{
ResultSet
rs
=
prep
.
getResultSet
();
while
(!
stop
&&
rs
.
next
())
{
// maybe get the data as well
}
rs
.
close
();
}
}
}
}
time
=
System
.
currentTimeMillis
()
-
time
;
StatementBuilder
buff
=
new
StatementBuilder
();
buff
.
append
(
time
).
append
(
" ms: "
).
append
(
count
).
append
(
" * "
);
if
(
prepared
)
{
buff
.
append
(
"(Prepared) "
);
}
else
{
buff
.
append
(
"(Statement) "
);
}
buff
.
append
(
'('
);
for
(
int
p
:
params
)
{
buff
.
appendExceptFirst
(
", "
);
buff
.
append
(
p
==
0
?
"i"
:
"rnd"
);
}
return
buff
.
append
(
") "
).
append
(
sql
).
toString
();
}
private
String
getCommandHistoryString
()
{
StringBuilder
buff
=
new
StringBuilder
();
ArrayList
<
String
>
history
=
session
.
getCommandHistory
();
buff
.
append
(
"<table cellspacing=0 cellpadding=0>"
+
"<tr><th></th><th>Command</th></tr>"
);
for
(
int
i
=
history
.
size
()
-
1
;
i
>=
0
;
i
--)
{
String
sql
=
history
.
get
(
i
);
buff
.
append
(
"<tr><td><a href=\"getHistory.do?id="
).
append
(
i
).
append
(
"&jsessionid=${sessionId}\" target=\"h2query\" >"
).
append
(
"<img width=16 height=16 src=\"ico_write.gif\" "
+
"onmouseover = \"this.className ='icon_hover'\" "
).
append
(
"onmouseout = \"this.className ='icon'\" "
+
"class=\"icon\" alt=\"${text.resultEdit.edit}\" "
).
append
(
"title=\"${text.resultEdit.edit}\" border=\"1\"/></a>"
).
append
(
"</td><td>"
).
append
(
PageParser
.
escapeHtml
(
sql
)).
append
(
"</td></tr>"
);
}
buff
.
append
(
"</table>"
);
return
buff
.
toString
();
}
private
static
String
getParameterResultSet
(
ParameterMetaData
meta
)
throws
SQLException
{
StringBuilder
buff
=
new
StringBuilder
();
if
(
meta
==
null
)
{
return
"No parameter meta data"
;
}
buff
.
append
(
"<table cellspacing=0 cellpadding=0>"
).
append
(
"<tr><th>className</th><th>mode</th><th>type</th>"
).
append
(
"<th>typeName</th><th>precision</th><th>scale</th></tr>"
);
for
(
int
i
=
0
;
i
<
meta
.
getParameterCount
();
i
++)
{
buff
.
append
(
"</tr><td>"
).
append
(
meta
.
getParameterClassName
(
i
+
1
)).
append
(
"</td><td>"
).
append
(
meta
.
getParameterMode
(
i
+
1
)).
append
(
"</td><td>"
).
append
(
meta
.
getParameterType
(
i
+
1
)).
append
(
"</td><td>"
).
append
(
meta
.
getParameterTypeName
(
i
+
1
)).
append
(
"</td><td>"
).
append
(
meta
.
getPrecision
(
i
+
1
)).
append
(
"</td><td>"
).
append
(
meta
.
getScale
(
i
+
1
)).
append
(
"</td></tr>"
);
}
buff
.
append
(
"</table>"
);
return
buff
.
toString
();
}
private
String
getResultSet
(
String
sql
,
ResultSet
rs
,
boolean
metadata
,
boolean
list
,
boolean
edit
,
long
time
,
boolean
allowEdit
)
throws
SQLException
{
int
maxrows
=
getMaxrows
();
time
=
System
.
currentTimeMillis
()
-
time
;
StringBuilder
buff
=
new
StringBuilder
();
if
(
edit
)
{
buff
.
append
(
"<form id=\"editing\" name=\"editing\" method=\"post\" "
+
"action=\"editResult.do?jsessionid=${sessionId}\" "
+
"id=\"mainForm\" target=\"h2result\">"
+
"<input type=\"hidden\" name=\"op\" value=\"1\" />"
+
"<input type=\"hidden\" name=\"row\" value=\"\" />"
+
"<table cellspacing=0 cellpadding=0 id=\"editTable\">"
);
}
else
{
buff
.
append
(
"<table cellspacing=0 cellpadding=0>"
);
}
if
(
metadata
)
{
SimpleResultSet
r
=
new
SimpleResultSet
();
r
.
addColumn
(
"#"
,
Types
.
INTEGER
,
0
,
0
);
r
.
addColumn
(
"label"
,
Types
.
VARCHAR
,
0
,
0
);
r
.
addColumn
(
"catalog"
,
Types
.
VARCHAR
,
0
,
0
);
r
.
addColumn
(
"schema"
,
Types
.
VARCHAR
,
0
,
0
);
r
.
addColumn
(
"table"
,
Types
.
VARCHAR
,
0
,
0
);
r
.
addColumn
(
"column"
,
Types
.
VARCHAR
,
0
,
0
);
r
.
addColumn
(
"type"
,
Types
.
INTEGER
,
0
,
0
);
r
.
addColumn
(
"typeName"
,
Types
.
VARCHAR
,
0
,
0
);
r
.
addColumn
(
"class"
,
Types
.
VARCHAR
,
0
,
0
);
r
.
addColumn
(
"precision"
,
Types
.
INTEGER
,
0
,
0
);
r
.
addColumn
(
"scale"
,
Types
.
INTEGER
,
0
,
0
);
r
.
addColumn
(
"displaySize"
,
Types
.
INTEGER
,
0
,
0
);
r
.
addColumn
(
"autoIncrement"
,
Types
.
BOOLEAN
,
0
,
0
);
r
.
addColumn
(
"caseSensitive"
,
Types
.
BOOLEAN
,
0
,
0
);
r
.
addColumn
(
"currency"
,
Types
.
BOOLEAN
,
0
,
0
);
r
.
addColumn
(
"nullable"
,
Types
.
INTEGER
,
0
,
0
);
r
.
addColumn
(
"readOnly"
,
Types
.
BOOLEAN
,
0
,
0
);
r
.
addColumn
(
"searchable"
,
Types
.
BOOLEAN
,
0
,
0
);
r
.
addColumn
(
"signed"
,
Types
.
BOOLEAN
,
0
,
0
);
r
.
addColumn
(
"writable"
,
Types
.
BOOLEAN
,
0
,
0
);
r
.
addColumn
(
"definitelyWritable"
,
Types
.
BOOLEAN
,
0
,
0
);
ResultSetMetaData
m
=
rs
.
getMetaData
();
for
(
int
i
=
1
;
i
<=
m
.
getColumnCount
();
i
++)
{
r
.
addRow
(
i
,
m
.
getColumnLabel
(
i
),
m
.
getCatalogName
(
i
),
m
.
getSchemaName
(
i
),
m
.
getTableName
(
i
),
m
.
getColumnName
(
i
),
m
.
getColumnType
(
i
),
m
.
getColumnTypeName
(
i
),
m
.
getColumnClassName
(
i
),
m
.
getPrecision
(
i
),
m
.
getScale
(
i
),
m
.
getColumnDisplaySize
(
i
),
m
.
isAutoIncrement
(
i
),
m
.
isCaseSensitive
(
i
),
m
.
isCurrency
(
i
),
m
.
isNullable
(
i
),
m
.
isReadOnly
(
i
),
m
.
isSearchable
(
i
),
m
.
isSigned
(
i
),
m
.
isWritable
(
i
),
m
.
isDefinitelyWritable
(
i
));
}
rs
=
r
;
}
ResultSetMetaData
meta
=
rs
.
getMetaData
();
int
columns
=
meta
.
getColumnCount
();
int
rows
=
0
;
if
(
list
)
{
buff
.
append
(
"<tr><th>Column</th><th>Data</th></tr><tr>"
);
while
(
rs
.
next
())
{
if
(
maxrows
>
0
&&
rows
>=
maxrows
)
{
break
;
}
rows
++;
buff
.
append
(
"<tr><td>Row #</td><td>"
).
append
(
rows
).
append
(
"</tr>"
);
for
(
int
i
=
0
;
i
<
columns
;
i
++)
{
buff
.
append
(
"<tr><td>"
).
append
(
PageParser
.
escapeHtml
(
meta
.
getColumnLabel
(
i
+
1
))).
append
(
"</td><td>"
).
append
(
escapeData
(
rs
,
i
+
1
)).
append
(
"</td></tr>"
);
}
}
}
else
{
buff
.
append
(
"<tr>"
);
if
(
edit
)
{
buff
.
append
(
"<th>${text.resultEdit.action}</th>"
);
}
for
(
int
i
=
0
;
i
<
columns
;
i
++)
{
buff
.
append
(
"<th>"
).
append
(
PageParser
.
escapeHtml
(
meta
.
getColumnLabel
(
i
+
1
))).
append
(
"</th>"
);
}
buff
.
append
(
"</tr>"
);
while
(
rs
.
next
())
{
if
(
maxrows
>
0
&&
rows
>=
maxrows
)
{
break
;
}
rows
++;
buff
.
append
(
"<tr>"
);
if
(
edit
)
{
buff
.
append
(
"<td>"
).
append
(
"<img onclick=\"javascript:editRow("
).
append
(
rs
.
getRow
()).
append
(
",'${sessionId}', '${text.resultEdit.save}', "
+
"'${text.resultEdit.cancel}'"
).
append
(
")\" width=16 height=16 src=\"ico_write.gif\" "
+
"onmouseover = \"this.className ='icon_hover'\" "
+
"onmouseout = \"this.className ='icon'\" "
+
"class=\"icon\" alt=\"${text.resultEdit.edit}\" "
+
"title=\"${text.resultEdit.edit}\" border=\"1\"/>"
).
append
(
"<a href=\"editResult.do?op=2&row="
).
append
(
rs
.
getRow
()).
append
(
"&jsessionid=${sessionId}\" target=\"h2result\" >"
+
"<img width=16 height=16 src=\"ico_remove.gif\" "
+
"onmouseover = \"this.className ='icon_hover'\" "
+
"onmouseout = \"this.className ='icon'\" "
+
"class=\"icon\" alt=\"${text.resultEdit.delete}\" "
+
"title=\"${text.resultEdit.delete}\" border=\"1\" /></a>"
).
append
(
"</td>"
);
}
for
(
int
i
=
0
;
i
<
columns
;
i
++)
{
buff
.
append
(
"<td>"
).
append
(
escapeData
(
rs
,
i
+
1
)).
append
(
"</td>"
);
}
buff
.
append
(
"</tr>"
);
}
}
boolean
isUpdatable
=
false
;
try
{
if
(!
session
.
getContents
().
isDB2
())
{
isUpdatable
=
rs
.
getConcurrency
()
==
ResultSet
.
CONCUR_UPDATABLE
&&
rs
.
getType
()
!=
ResultSet
.
TYPE_FORWARD_ONLY
;
}
}
catch
(
NullPointerException
e
)
{
// ignore
// workaround for a JDBC-ODBC bridge problem
}
if
(
edit
)
{
ResultSet
old
=
session
.
result
;
if
(
old
!=
null
)
{
old
.
close
();
}
session
.
result
=
rs
;
}
else
{
rs
.
close
();
}
if
(
edit
)
{
buff
.
append
(
"<tr><td>"
).
append
(
"<img onclick=\"javascript:editRow(-1, "
+
"'${sessionId}', '${text.resultEdit.save}', '${text.resultEdit.cancel}'"
).
append
(
")\" width=16 height=16 src=\"ico_add.gif\" "
+
"onmouseover = \"this.className ='icon_hover'\" "
+
"onmouseout = \"this.className ='icon'\" "
+
"class=\"icon\" alt=\"${text.resultEdit.add}\" "
+
"title=\"${text.resultEdit.add}\" border=\"1\"/>"
).
append
(
"</td>"
);
for
(
int
i
=
0
;
i
<
columns
;
i
++)
{
buff
.
append
(
"<td></td>"
);
}
buff
.
append
(
"</tr>"
);
}
buff
.
append
(
"</table>"
);
if
(
edit
)
{
buff
.
append
(
"</form>"
);
}
if
(
rows
==
0
)
{
buff
.
append
(
"(${text.result.noRows}"
);
}
else
if
(
rows
==
1
)
{
buff
.
append
(
"(${text.result.1row}"
);
}
else
{
buff
.
append
(
'('
).
append
(
rows
).
append
(
" ${text.result.rows}"
);
}
buff
.
append
(
", "
);
time
=
System
.
currentTimeMillis
()
-
time
;
buff
.
append
(
time
).
append
(
" ms)"
);
if
(!
edit
&&
isUpdatable
&&
allowEdit
)
{
buff
.
append
(
"<br /><br />"
+
"<form name=\"editResult\" method=\"post\" "
+
"action=\"query.do?jsessionid=${sessionId}\" target=\"h2result\">"
+
"<input type=\"submit\" class=\"button\" "
+
"value=\"${text.resultEdit.editResult}\" />"
+
"<input type=\"hidden\" name=\"sql\" value=\"@edit "
).
append
(
PageParser
.
escapeHtmlData
(
sql
)).
append
(
"\" /></form>"
);
}
return
buff
.
toString
();
}
/**
* Save the current connection settings to the properties file.
*
* @return the file to open afterwards
*/
private
String
settingSave
()
{
ConnectionInfo
info
=
new
ConnectionInfo
();
info
.
name
=
attributes
.
getProperty
(
"name"
,
""
);
info
.
driver
=
attributes
.
getProperty
(
"driver"
,
""
);
info
.
url
=
attributes
.
getProperty
(
"url"
,
""
);
info
.
user
=
attributes
.
getProperty
(
"user"
,
""
);
server
.
updateSetting
(
info
);
attributes
.
put
(
"setting"
,
info
.
name
);
server
.
saveProperties
(
null
);
return
"index.do"
;
}
private
static
String
escapeData
(
ResultSet
rs
,
int
columnIndex
)
throws
SQLException
{
String
d
=
rs
.
getString
(
columnIndex
);
if
(
d
==
null
)
{
return
"<i>null</i>"
;
}
else
if
(
d
.
length
()
>
100000
)
{
String
s
;
if
(
isBinary
(
rs
.
getMetaData
().
getColumnType
(
columnIndex
)))
{
s
=
PageParser
.
escapeHtml
(
d
.
substring
(
0
,
6
))
+
"... ("
+
(
d
.
length
()
/
2
)
+
" ${text.result.bytes})"
;
}
else
{
s
=
PageParser
.
escapeHtml
(
d
.
substring
(
0
,
100
))
+
"... ("
+
d
.
length
()
+
" ${text.result.characters})"
;
}
return
"<div style='display: none'>=+</div>"
+
s
;
}
else
if
(
d
.
equals
(
"null"
)
||
d
.
startsWith
(
"= "
)
||
d
.
startsWith
(
"=+"
))
{
return
"<div style='display: none'>= </div>"
+
PageParser
.
escapeHtml
(
d
);
}
else
if
(
d
.
equals
(
""
))
{
// PageParser.escapeHtml replaces "" with a non-breaking space
return
""
;
}
return
PageParser
.
escapeHtml
(
d
);
}
private
static
boolean
isBinary
(
int
sqlType
)
{
switch
(
sqlType
)
{
case
Types
.
BINARY
:
case
Types
.
BLOB
:
case
Types
.
JAVA_OBJECT
:
case
Types
.
LONGVARBINARY
:
case
Types
.
OTHER
:
case
Types
.
VARBINARY
:
return
true
;
}
return
false
;
}
private
void
unescapeData
(
String
x
,
ResultSet
rs
,
int
columnIndex
)
throws
SQLException
{
if
(
x
.
equals
(
"null"
))
{
rs
.
updateNull
(
columnIndex
);
return
;
}
else
if
(
x
.
startsWith
(
"=+"
))
{
// don't update
return
;
}
else
if
(
x
.
equals
(
"=*"
))
{
// set an appropriate default value
int
type
=
rs
.
getMetaData
().
getColumnType
(
columnIndex
);
switch
(
type
)
{
case
Types
.
TIME
:
rs
.
updateString
(
columnIndex
,
"12:00:00"
);
break
;
case
Types
.
TIMESTAMP
:
case
Types
.
DATE
:
rs
.
updateString
(
columnIndex
,
"2001-01-01"
);
break
;
default
:
rs
.
updateString
(
columnIndex
,
"1"
);
break
;
}
return
;
}
else
if
(
x
.
startsWith
(
"= "
))
{
x
=
x
.
substring
(
2
);
}
ResultSetMetaData
meta
=
rs
.
getMetaData
();
int
type
=
meta
.
getColumnType
(
columnIndex
);
if
(
session
.
getContents
().
isH2
())
{
rs
.
updateString
(
columnIndex
,
x
);
return
;
}
switch
(
type
)
{
case
Types
.
BIGINT
:
rs
.
updateLong
(
columnIndex
,
Long
.
decode
(
x
));
break
;
case
Types
.
DECIMAL
:
rs
.
updateBigDecimal
(
columnIndex
,
new
BigDecimal
(
x
));
break
;
case
Types
.
DOUBLE
:
case
Types
.
FLOAT
:
rs
.
updateDouble
(
columnIndex
,
Double
.
parseDouble
(
x
));
break
;
case
Types
.
REAL
:
rs
.
updateFloat
(
columnIndex
,
Float
.
parseFloat
(
x
));
break
;
case
Types
.
INTEGER
:
rs
.
updateInt
(
columnIndex
,
Integer
.
decode
(
x
));
break
;
case
Types
.
TINYINT
:
rs
.
updateShort
(
columnIndex
,
Short
.
decode
(
x
));
break
;
default
:
rs
.
updateString
(
columnIndex
,
x
);
}
}
private
String
settingRemove
()
{
String
setting
=
attributes
.
getProperty
(
"name"
,
""
);
server
.
removeSetting
(
setting
);
ArrayList
<
ConnectionInfo
>
settings
=
server
.
getSettings
();
if
(
settings
.
size
()
>
0
)
{
attributes
.
put
(
"setting"
,
settings
.
get
(
0
));
}
server
.
saveProperties
(
null
);
return
"index.do"
;
}
/**
* Get the current mime type.
*
* @return the mime type
*/
String
getMimeType
()
{
return
mimeType
;
}
boolean
getCache
()
{
return
cache
;
}
WebSession
getSession
()
{
return
session
;
}
private
void
trace
(
String
s
)
{
server
.
trace
(
s
);
}
}
\ No newline at end of file
grog-webapp/src/main/java/org/legrog/util/WebServer.java
deleted
100644 → 0
View file @
e8aef6f
package
org
.
legrog
.
util
;
// Code copied from org.h2.server.web.WebServer
/*
* Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
//package org.h2.server.web;
import
java.io.File
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.OutputStream
;
import
java.net.ServerSocket
;
import
java.net.Socket
;
import
java.sql.Connection
;
import
java.sql.SQLException
;
import
java.text.SimpleDateFormat
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.Locale
;
import
java.util.Map
;
import
java.util.Map.Entry
;
import
java.util.Properties
;
import
java.util.Set
;
import
java.util.TimeZone
;
import
org.h2.engine.Constants
;
import
org.h2.engine.SysProperties
;
import
org.h2.message.DbException
;
import
org.h2.server.Service
;
import
org.h2.server.ShutdownHandler
;
import
org.h2.store.fs.FileUtils
;
import
org.h2.util.JdbcUtils
;
import
org.h2.util.MathUtils
;
import
org.h2.util.NetUtils
;
import
org.h2.util.New
;
import
org.h2.util.SortedProperties
;
import
org.h2.util.StringUtils
;
import
org.h2.util.Tool
;
import
org.h2.util.Utils
;
/**
* The web server is a simple standalone HTTP server that implements the H2
* Console application. It is not optimized for performance.
*/
public
class
WebServer
implements
Service
{
static
final
String
[][]
LANGUAGES
=
{
{
"cs"
,
"\u010ce\u0161tina"
},
{
"de"
,
"Deutsch"
},
{
"en"
,
"English"
},
{
"es"
,
"Espa\u00f1ol"
},
{
"fr"
,
"Fran\u00e7ais"
},
{
"hu"
,
"Magyar"
},
{
"ko"
,
"\ud55c\uad6d\uc5b4"
},
{
"in"
,
"Indonesia"
},
{
"it"
,
"Italiano"
},
{
"ja"
,
"\u65e5\u672c\u8a9e"
},
{
"nl"
,
"Nederlands"
},
{
"pl"
,
"Polski"
},
{
"pt_BR"
,
"Portugu\u00eas (Brasil)"
},
{
"pt_PT"
,
"Portugu\u00eas (Europeu)"
},
{
"ru"
,
"\u0440\u0443\u0441\u0441\u043a\u0438\u0439"
},
{
"sk"
,
"Slovensky"
},
{
"tr"
,
"T\u00fcrk\u00e7e"
},
{
"uk"
,
"\u0423\u043A\u0440\u0430\u0457\u043D\u0441\u044C\u043A\u0430"
},
{
"zh_CN"
,
"\u4e2d\u6587 (\u7b80\u4f53)"
},
{
"zh_TW"
,
"\u4e2d\u6587 (\u7e41\u9ad4)"
},
};
private
static
final
String
COMMAND_HISTORY
=
"commandHistory"
;
private
static
final
String
DEFAULT_LANGUAGE
=
"en"
;
private
static
final
String
[]
GENERIC
=
{
"Generic JNDI Data Source|javax.naming.InitialContext|"
+
"java:comp/env/jdbc/Test|sa"
,
"Generic Firebird Server|org.firebirdsql.jdbc.FBDriver|"
+
"jdbc:firebirdsql:localhost:c:/temp/firebird/test|sysdba"
,
"Generic SQLite|org.sqlite.JDBC|"
+
"jdbc:sqlite:test|sa"
,
"Generic DB2|com.ibm.db2.jcc.DB2Driver|"
+
"jdbc:db2://localhost/test|"
,
"Generic Oracle|oracle.jdbc.driver.OracleDriver|"
+
"jdbc:oracle:thin:@localhost:1521:XE|sa"
,
"Generic MS SQL Server 2000|com.microsoft.jdbc.sqlserver.SQLServerDriver|"
+
"jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=sqlexpress|sa"
,
"Generic MS SQL Server 2005|com.microsoft.sqlserver.jdbc.SQLServerDriver|"
+
"jdbc:sqlserver://localhost;DatabaseName=test|sa"
,
"Generic PostgreSQL|org.postgresql.Driver|"
+
"jdbc:postgresql:test|"
,
"Generic MySQL|com.mysql.jdbc.Driver|"
+
"jdbc:mysql://localhost:3306/test|"
,
"Generic HSQLDB|org.hsqldb.jdbcDriver|"
+
"jdbc:hsqldb:test;hsqldb.default_table_type=cached|sa"
,
"Generic Derby (Server)|org.apache.derby.jdbc.ClientDriver|"
+
"jdbc:derby://localhost:1527/test;create=true|sa"
,
"Generic Derby (Embedded)|org.apache.derby.jdbc.EmbeddedDriver|"
+
"jdbc:derby:test;create=true|sa"
,
"Generic H2 (Server)|org.h2.Driver|"
+
"jdbc:h2:tcp://localhost/~/test|sa"
,
// this will be listed on top for new installations
"Generic H2 (Embedded)|org.h2.Driver|"
+
"jdbc:h2:~/test|sa"
,
};
private
static
int
ticker
;
/**
* The session timeout (the default is 30 minutes).
*/
private
static
final
long
SESSION_TIMEOUT
=
SysProperties
.
CONSOLE_TIMEOUT
;
// public static void main(String... args) throws IOException {
// String s = IOUtils.readStringAndClose(new java.io.FileReader(
// // "src/main/org/h2/server/web/res/_text_cs.prop"), -1);
// "src/main/org/h2/res/_messages_cs.prop"), -1);
// System.out.println(StringUtils.javaEncode("..."));
// String[] list = Locale.getISOLanguages();
// for (int i = 0; i < list.length; i++) {
// System.out.print(list[i] + " ");
// }
// System.out.println();
// String l = "de";
// String lang = new java.util.Locale(l).
// getDisplayLanguage(new java.util.Locale(l));
// System.out.println(new java.util.Locale(l).getDisplayLanguage());
// System.out.println(lang);
// java.util.Locale.CHINESE.getDisplayLanguage(java.util.Locale.CHINESE);
// for (int i = 0; i < lang.length(); i++) {
// System.out.println(Integer.toHexString(lang.charAt(i)) + " ");
// }
// }
// private URLClassLoader urlClassLoader;
private
int
port
;
private
boolean
allowOthers
;
private
boolean
isDaemon
;
private
final
Set
<
WebThread
>
running
=
Collections
.
synchronizedSet
(
new
HashSet
<
WebThread
>());
private
boolean
ssl
;
private
final
HashMap
<
String
,
ConnectionInfo
>
connInfoMap
=
New
.
hashMap
();
private
long
lastTimeoutCheck
;
private
final
HashMap
<
String
,
WebSession
>
sessions
=
New
.
hashMap
();
private
final
HashSet
<
String
>
languages
=
New
.
hashSet
();
private
String
startDateTime
;
private
ServerSocket
serverSocket
;
private
String
url
;
private
ShutdownHandler
shutdownHandler
;
private
Thread
listenerThread
;
private
boolean
ifExists
;
private
boolean
trace
;
private
TranslateThread
translateThread
;
private
boolean
allowChunked
=
true
;
private
String
serverPropertiesDir
=
Constants
.
SERVER_PROPERTIES_DIR
;
// null means the history is not allowed to be stored
private
String
commandHistoryString
;
/**
* Read the given file from the file system or from the resources.
*
* @param file the file name
* @return the data
*/
byte
[]
getFile
(
String
file
)
throws
IOException
{
trace
(
"getFile <"
+
file
+
">"
);
byte
[]
data
=
Utils
.
getResource
(
"/org/h2/server/web/res/"
+
file
);
if
(
data
==
null
)
{
trace
(
" null"
);
}
else
{
trace
(
" size="
+
data
.
length
);
}
return
data
;
}
/**
* Check if this is a simple name (only contains '.', '-', '_', letters, or
* digits).
*
* @param s the string
* @return true if it's a simple name
*/
static
boolean
isSimpleName
(
String
s
)
{
for
(
char
c
:
s
.
toCharArray
())
{
if
(
c
!=
'.'
&&
c
!=
'_'
&&
c
!=
'-'
&&
!
Character
.
isLetterOrDigit
(
c
))
{
return
false
;
}
}
return
true
;
}
/**
* Remove this web thread from the set of running threads.
*
* @param t the thread to remove
*/
synchronized
void
remove
(
WebThread
t
)
{
running
.
remove
(
t
);
}
private
static
String
generateSessionId
()
{
byte
[]
buff
=
MathUtils
.
secureRandomBytes
(
16
);
return
StringUtils
.
convertBytesToHex
(
buff
);
}
/**
* Get the web session object for the given session id.
*
* @param sessionId the session id
* @return the web session or null
*/
WebSession
getSession
(
String
sessionId
)
{
long
now
=
System
.
currentTimeMillis
();
if
(
lastTimeoutCheck
+
SESSION_TIMEOUT
<
now
)
{
for
(
String
id
:
New
.
arrayList
(
sessions
.
keySet
()))
{
WebSession
session
=
sessions
.
get
(
id
);
if
(
session
.
lastAccess
+
SESSION_TIMEOUT
<
now
)
{
trace
(
"timeout for "
+
id
);
sessions
.
remove
(
id
);
}
}
lastTimeoutCheck
=
now
;
}
WebSession
session
=
sessions
.
get
(
sessionId
);
if
(
session
!=
null
)
{
session
.
lastAccess
=
System
.
currentTimeMillis
();
}
return
session
;
}
/**
* Create a new web session id and object.
*
* @param hostAddr the host address
* @return the web session object
*/
WebSession
createNewSession
(
String
hostAddr
)
{
String
newId
;
do
{
newId
=
generateSessionId
();
}
while
(
sessions
.
get
(
newId
)
!=
null
);
WebSession
session
=
new
WebSession
(
this
);
session
.
lastAccess
=
System
.
currentTimeMillis
();
session
.
put
(
"sessionId"
,
newId
);
session
.
put
(
"ip"
,
hostAddr
);
session
.
put
(
"language"
,
DEFAULT_LANGUAGE
);
session
.
put
(
"frame-border"
,
"0"
);
session
.
put
(
"frameset-border"
,
"4"
);
sessions
.
put
(
newId
,
session
);
// always read the english translation,
// so that untranslated text appears at least in english
readTranslations
(
session
,
DEFAULT_LANGUAGE
);
return
getSession
(
newId
);
}
String
getStartDateTime
()
{
if
(
startDateTime
==
null
)
{
SimpleDateFormat
format
=
new
SimpleDateFormat
(
"EEE, d MMM yyyy HH:mm:ss z"
,
new
Locale
(
"en"
,
""
));
format
.
setTimeZone
(
TimeZone
.
getTimeZone
(
"GMT"
));
startDateTime
=
format
.
format
(
System
.
currentTimeMillis
());
}
return
startDateTime
;
}
@Override
public
void
init
(
String
...
args
)
{
// set the serverPropertiesDir, because it's used in loadProperties()
for
(
int
i
=
0
;
args
!=
null
&&
i
<
args
.
length
;
i
++)
{
if
(
"-properties"
.
equals
(
args
[
i
]))
{
serverPropertiesDir
=
args
[++
i
];
}
}
Properties
prop
=
loadProperties
();
port
=
SortedProperties
.
getIntProperty
(
prop
,
"webPort"
,
Constants
.
DEFAULT_HTTP_PORT
);
ssl
=
SortedProperties
.
getBooleanProperty
(
prop
,
"webSSL"
,
false
);
allowOthers
=
SortedProperties
.
getBooleanProperty
(
prop
,
"webAllowOthers"
,
false
);
commandHistoryString
=
prop
.
getProperty
(
COMMAND_HISTORY
);
for
(
int
i
=
0
;
args
!=
null
&&
i
<
args
.
length
;
i
++)
{
String
a
=
args
[
i
];
if
(
Tool
.
isOption
(
a
,
"-webPort"
))
{
port
=
Integer
.
decode
(
args
[++
i
]);
}
else
if
(
Tool
.
isOption
(
a
,
"-webSSL"
))
{
ssl
=
true
;
}
else
if
(
Tool
.
isOption
(
a
,
"-webAllowOthers"
))
{
allowOthers
=
true
;
}
else
if
(
Tool
.
isOption
(
a
,
"-webDaemon"
))
{
isDaemon
=
true
;
}
else
if
(
Tool
.
isOption
(
a
,
"-baseDir"
))
{
String
baseDir
=
args
[++
i
];
SysProperties
.
setBaseDir
(
baseDir
);
}
else
if
(
Tool
.
isOption
(
a
,
"-ifExists"
))
{
ifExists
=
true
;
}
else
if
(
Tool
.
isOption
(
a
,
"-properties"
))
{
// already set
i
++;
}
else
if
(
Tool
.
isOption
(
a
,
"-trace"
))
{
trace
=
true
;
}
}
// if (driverList != null) {
// try {
// String[] drivers =
// StringUtils.arraySplit(driverList, ',', false);
// URL[] urls = new URL[drivers.length];
// for(int i=0; i<drivers.length; i++) {
// urls[i] = new URL(drivers[i]);
// }
// urlClassLoader = URLClassLoader.newInstance(urls);
// } catch (MalformedURLException e) {
// TraceSystem.traceThrowable(e);
// }
// }
for
(
String
[]
lang
:
LANGUAGES
)
{
languages
.
add
(
lang
[
0
]);
}
updateURL
();
}
@Override
public
String
getURL
()
{
updateURL
();
return
url
;
}
private
void
updateURL
()
{
try
{
url
=
(
ssl
?
"https"
:
"http"
)
+
"://"
+
NetUtils
.
getLocalAddress
()
+
":"
+
port
;
}
catch
(
NoClassDefFoundError
e
)
{
// Google App Engine does not allow java.net.InetAddress
}
}
@Override
public
void
start
()
{
serverSocket
=
NetUtils
.
createServerSocket
(
port
,
ssl
);
port
=
serverSocket
.
getLocalPort
();
updateURL
();
}
@Override
public
void
listen
()
{
this
.
listenerThread
=
Thread
.
currentThread
();
try
{
while
(
serverSocket
!=
null
)
{
Socket
s
=
serverSocket
.
accept
();
WebThread
c
=
new
WebThread
(
s
,
this
);
running
.
add
(
c
);
c
.
start
();
}
}
catch
(
Exception
e
)
{
trace
(
e
.
toString
());
}
}
@Override
public
boolean
isRunning
(
boolean
traceError
)
{
if
(
serverSocket
==
null
)
{
return
false
;
}
try
{
Socket
s
=
NetUtils
.
createLoopbackSocket
(
port
,
ssl
);
s
.
close
();
return
true
;
}
catch
(
Exception
e
)
{
if
(
traceError
)
{
traceError
(
e
);
}
return
false
;
}
}
public
boolean
isStopped
()
{
return
serverSocket
==
null
;
}
@Override
public
void
stop
()
{
if
(
serverSocket
!=
null
)
{
try
{
serverSocket
.
close
();
}
catch
(
IOException
e
)
{
traceError
(
e
);
}
serverSocket
=
null
;
}
if
(
listenerThread
!=
null
)
{
try
{
listenerThread
.
join
(
1000
);
}
catch
(
InterruptedException
e
)
{
DbException
.
traceThrowable
(
e
);
}
}
// TODO server: using a boolean 'now' argument? a timeout?
for
(
WebSession
session
:
New
.
arrayList
(
sessions
.
values
()))
{
session
.
close
();
}
for
(
WebThread
c
:
New
.
arrayList
(
running
))
{
try
{
c
.
stopNow
();
c
.
join
(
100
);
}
catch
(
Exception
e
)
{
traceError
(
e
);
}
}
}
/**
* Write trace information if trace is enabled.
*
* @param s the message to write
*/
void
trace
(
String
s
)
{
if
(
trace
)
{
System
.
out
.
println
(
s
);
}
}
/**
* Write the stack trace if trace is enabled.
*
* @param e the exception
*/
void
traceError
(
Throwable
e
)
{
if
(
trace
)
{
e
.
printStackTrace
();
}
}
/**
* Check if this language is supported / translated.
*
* @param language the language
* @return true if a translation is available
*/
boolean
supportsLanguage
(
String
language
)
{
return
languages
.
contains
(
language
);
}
/**
* Read the translation for this language and save them in the 'text'
* property of this session.
*
* @param session the session
* @param language the language
*/
void
readTranslations
(
WebSession
session
,
String
language
)
{
Properties
text
=
new
Properties
();
try
{
trace
(
"translation: "
+
language
);
byte
[]
trans
=
getFile
(
"_text_"
+
language
+
".prop"
);
trace
(
" "
+
new
String
(
trans
));
text
=
SortedProperties
.
fromLines
(
new
String
(
trans
,
Constants
.
UTF8
));
// remove starting # (if not translated yet)
for
(
Entry
<
Object
,
Object
>
entry
:
text
.
entrySet
())
{
String
value
=
(
String
)
entry
.
getValue
();
if
(
value
.
startsWith
(
"#"
))
{
entry
.
setValue
(
value
.
substring
(
1
));
}
}
}
catch
(
IOException
e
)
{
DbException
.
traceThrowable
(
e
);
}
session
.
put
(
"text"
,
new
HashMap
<
Object
,
Object
>(
text
));
}
ArrayList
<
HashMap
<
String
,
Object
>>
getSessions
()
{
ArrayList
<
HashMap
<
String
,
Object
>>
list
=
New
.
arrayList
();
for
(
WebSession
s
:
sessions
.
values
())
{
list
.
add
(
s
.
getInfo
());
}
return
list
;
}
@Override
public
String
getType
()
{
return
"Web Console"
;
}
@Override
public
String
getName
()
{
return
"H2 Console Server"
;
}
void
setAllowOthers
(
boolean
b
)
{
allowOthers
=
b
;
}
@Override
public
boolean
getAllowOthers
()
{
return
allowOthers
;
}
void
setSSL
(
boolean
b
)
{
ssl
=
b
;
}
void
setPort
(
int
port
)
{
this
.
port
=
port
;
}
boolean
getSSL
()
{
return
ssl
;
}
@Override
public
int
getPort
()
{
return
port
;
}
public
boolean
isCommandHistoryAllowed
()
{
return
commandHistoryString
!=
null
;
}
public
void
setCommandHistoryAllowed
(
boolean
allowed
)
{
if
(
allowed
)
{
if
(
commandHistoryString
==
null
)
{
commandHistoryString
=
""
;
}
}
else
{
commandHistoryString
=
null
;
}
}
public
ArrayList
<
String
>
getCommandHistoryList
()
{
ArrayList
<
String
>
result
=
New
.
arrayList
();
if
(
commandHistoryString
==
null
)
{
return
result
;
}
// Split the commandHistoryString on non-escaped semicolons
// and unescape it.
StringBuilder
sb
=
new
StringBuilder
();
for
(
int
end
=
0
;;
end
++)
{
if
(
end
==
commandHistoryString
.
length
()
||
commandHistoryString
.
charAt
(
end
)
==
';'
)
{
if
(
sb
.
length
()
>
0
)
{
result
.
add
(
sb
.
toString
());
sb
.
delete
(
0
,
sb
.
length
());
}
if
(
end
==
commandHistoryString
.
length
())
{
break
;
}
}
else
if
(
commandHistoryString
.
charAt
(
end
)
==
'\\'
&&
end
<
commandHistoryString
.
length
()
-
1
)
{
sb
.
append
(
commandHistoryString
.
charAt
(++
end
));
}
else
{
sb
.
append
(
commandHistoryString
.
charAt
(
end
));
}
}
return
result
;
}
/**
* Save the command history to the properties file.
*
* @param commandHistory the history
*/
public
void
saveCommandHistoryList
(
ArrayList
<
String
>
commandHistory
)
{
StringBuilder
sb
=
new
StringBuilder
();
for
(
String
s
:
commandHistory
)
{
if
(
sb
.
length
()
>
0
)
{
sb
.
append
(
';'
);
}
sb
.
append
(
s
.
replace
(
"\\"
,
"\\\\"
).
replace
(
";"
,
"\\;"
));
}
commandHistoryString
=
sb
.
toString
();
saveProperties
(
null
);
}
/**
* Get the connection information for this setting.
*
* @param name the setting name
* @return the connection information
*/
ConnectionInfo
getSetting
(
String
name
)
{
return
connInfoMap
.
get
(
name
);
}
/**
* Update a connection information setting.
*
* @param info the connection information
*/
void
updateSetting
(
ConnectionInfo
info
)
{
connInfoMap
.
put
(
info
.
name
,
info
);
info
.
lastAccess
=
ticker
++;
}
/**
* Remove a connection information setting from the list
*
* @param name the setting to remove
*/
void
removeSetting
(
String
name
)
{
connInfoMap
.
remove
(
name
);
}
private
Properties
loadProperties
()
{
try
{
if
(
"null"
.
equals
(
serverPropertiesDir
))
{
return
new
Properties
();
}
return
SortedProperties
.
loadProperties
(
serverPropertiesDir
+
"/"
+
Constants
.
SERVER_PROPERTIES_NAME
);
}
catch
(
Exception
e
)
{
DbException
.
traceThrowable
(
e
);
return
new
Properties
();
}
}
/**
* Get the list of connection information setting names.
*
* @return the connection info names
*/
String
[]
getSettingNames
()
{
ArrayList
<
ConnectionInfo
>
list
=
getSettings
();
String
[]
names
=
new
String
[
list
.
size
()];
for
(
int
i
=
0
;
i
<
list
.
size
();
i
++)
{
names
[
i
]
=
list
.
get
(
i
).
name
;
}
return
names
;
}
/**
* Get the list of connection info objects.
*
* @return the list
*/
synchronized
ArrayList
<
ConnectionInfo
>
getSettings
()
{
ArrayList
<
ConnectionInfo
>
settings
=
New
.
arrayList
();
if
(
connInfoMap
.
size
()
==
0
)
{
Properties
prop
=
loadProperties
();
if
(
prop
.
size
()
==
0
)
{
for
(
String
gen
:
GENERIC
)
{
ConnectionInfo
info
=
new
ConnectionInfo
(
gen
);
settings
.
add
(
info
);
updateSetting
(
info
);
}
}
else
{
for
(
int
i
=
0
;;
i
++)
{
String
data
=
prop
.
getProperty
(
String
.
valueOf
(
i
));
if
(
data
==
null
)
{
break
;
}
ConnectionInfo
info
=
new
ConnectionInfo
(
data
);
settings
.
add
(
info
);
updateSetting
(
info
);
}
}
}
else
{
settings
.
addAll
(
connInfoMap
.
values
());
}
Collections
.
sort
(
settings
);
return
settings
;
}
/**
* Save the settings to the properties file.
*
* @param prop null or the properties webPort, webAllowOthers, and webSSL
*/
synchronized
void
saveProperties
(
Properties
prop
)
{
try
{
if
(
prop
==
null
)
{
Properties
old
=
loadProperties
();
prop
=
new
SortedProperties
();
prop
.
setProperty
(
"webPort"
,
""
+
SortedProperties
.
getIntProperty
(
old
,
"webPort"
,
port
));
prop
.
setProperty
(
"webAllowOthers"
,
""
+
SortedProperties
.
getBooleanProperty
(
old
,
"webAllowOthers"
,
allowOthers
));
prop
.
setProperty
(
"webSSL"
,
""
+
SortedProperties
.
getBooleanProperty
(
old
,
"webSSL"
,
ssl
));
if
(
commandHistoryString
!=
null
)
{
prop
.
setProperty
(
COMMAND_HISTORY
,
commandHistoryString
);
}
}
ArrayList
<
ConnectionInfo
>
settings
=
getSettings
();
int
len
=
settings
.
size
();
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
ConnectionInfo
info
=
settings
.
get
(
i
);
if
(
info
!=
null
)
{
prop
.
setProperty
(
String
.
valueOf
(
len
-
i
-
1
),
info
.
getString
());
}
}
if
(!
"null"
.
equals
(
serverPropertiesDir
))
{
OutputStream
out
=
FileUtils
.
newOutputStream
(
serverPropertiesDir
+
"/"
+
Constants
.
SERVER_PROPERTIES_NAME
,
false
);
prop
.
store
(
out
,
"H2 Server Properties"
);
out
.
close
();
}
}
catch
(
Exception
e
)
{
DbException
.
traceThrowable
(
e
);
}
}
/**
* Open a database connection.
*
* @param driver the driver class name
* @param databaseUrl the database URL
* @param user the user name
* @param password the password
* @return the database connection
*/
Connection
getConnection
(
String
driver
,
String
databaseUrl
,
String
user
,
String
password
)
throws
SQLException
{
driver
=
driver
.
trim
();
databaseUrl
=
databaseUrl
.
trim
();
org
.
h2
.
Driver
.
load
();
Properties
p
=
new
Properties
();
p
.
setProperty
(
"user"
,
user
.
trim
());
// do not trim the password, otherwise an
// encrypted H2 database with empty user password doesn't work
p
.
setProperty
(
"password"
,
password
);
if
(
databaseUrl
.
startsWith
(
"jdbc:h2:"
))
{
if
(
ifExists
)
{
databaseUrl
+=
";IFEXISTS=TRUE"
;
}
// PostgreSQL would throw a NullPointerException
// if it is loaded before the H2 driver
// because it can't deal with non-String objects in the connection
// Properties
return
org
.
h2
.
Driver
.
load
().
connect
(
databaseUrl
,
p
);
}
// try {
// Driver dr = (Driver) urlClassLoader.
// loadClass(driver).newInstance();
// return dr.connect(url, p);
// } catch(ClassNotFoundException e2) {
// throw e2;
// }
return
JdbcUtils
.
getConnection
(
driver
,
databaseUrl
,
p
);
}
/**
* Shut down the web server.
*/
void
shutdown
()
{
if
(
shutdownHandler
!=
null
)
{
shutdownHandler
.
shutdown
();
}
}
public
void
setShutdownHandler
(
ShutdownHandler
shutdownHandler
)
{
this
.
shutdownHandler
=
shutdownHandler
;
}
/**
* Create a session with a given connection.
*
* @param conn the connection
* @return the URL of the web site to access this connection
*/
public
String
addSession
(
Connection
conn
)
throws
SQLException
{
WebSession
session
=
createNewSession
(
"local"
);
session
.
setShutdownServerOnDisconnect
();
session
.
setConnection
(
conn
);
session
.
put
(
"url"
,
conn
.
getMetaData
().
getURL
());
String
s
=
(
String
)
session
.
get
(
"sessionId"
);
return
url
+
"/frame.jsp?jsessionid="
+
s
;
}
/**
* The translate thread reads and writes the file translation.properties
* once a second.
*/
private
class
TranslateThread
extends
Thread
{
private
final
File
file
=
new
File
(
"translation.properties"
);
private
final
Map
<
Object
,
Object
>
translation
;
private
volatile
boolean
stopNow
;
TranslateThread
(
Map
<
Object
,
Object
>
translation
)
{
this
.
translation
=
translation
;
}
public
String
getFileName
()
{
return
file
.
getAbsolutePath
();
}
public
void
stopNow
()
{
this
.
stopNow
=
true
;
try
{
join
();
}
catch
(
InterruptedException
e
)
{
// ignore
}
}
@Override
public
void
run
()
{
while
(!
stopNow
)
{
try
{
SortedProperties
sp
=
new
SortedProperties
();
if
(
file
.
exists
())
{
InputStream
in
=
FileUtils
.
newInputStream
(
file
.
getName
());
sp
.
load
(
in
);
translation
.
putAll
(
sp
);
}
else
{
OutputStream
out
=
FileUtils
.
newOutputStream
(
file
.
getName
(),
false
);
sp
.
putAll
(
translation
);
sp
.
store
(
out
,
"Translation"
);
}
Thread
.
sleep
(
1000
);
}
catch
(
Exception
e
)
{
traceError
(
e
);
}
}
}
}
/**
* Start the translation thread that reads the file once a second.
*
* @param translation the translation map
* @return the name of the file to translate
*/
String
startTranslate
(
Map
<
Object
,
Object
>
translation
)
{
if
(
translateThread
!=
null
)
{
translateThread
.
stopNow
();
}
translateThread
=
new
TranslateThread
(
translation
);
translateThread
.
setDaemon
(
true
);
translateThread
.
start
();
return
translateThread
.
getFileName
();
}
@Override
public
boolean
isDaemon
()
{
return
isDaemon
;
}
void
setAllowChunked
(
boolean
allowChunked
)
{
this
.
allowChunked
=
allowChunked
;
}
boolean
getAllowChunked
()
{
return
allowChunked
;
}
}
\ No newline at end of file
grog-webapp/src/main/java/org/legrog/util/WebSession.java
deleted
100644 → 0
View file @
e8aef6f
package
org
.
legrog
.
util
;
// Code copied from org.h2.server.web.WebSession
/*
* Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
///package org.h2.server.web;
import
java.sql.Connection
;
import
java.sql.DatabaseMetaData
;
import
java.sql.ResultSet
;
import
java.sql.SQLException
;
import
java.sql.Statement
;
import
java.sql.Timestamp
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.Locale
;
import
org.h2.bnf.Bnf
;
import
org.h2.bnf.context.DbContents
;
import
org.h2.bnf.context.DbContextRule
;
import
org.h2.message.DbException
;
import
org.h2.util.New
;
/**
* The web session keeps all data of a user session.
* This class is used by the H2 Console.
*/
class
WebSession
{
private
static
final
int
MAX_HISTORY
=
1000
;
/**
* The last time this client sent a request.
*/
long
lastAccess
;
/**
* The session attribute map.
*/
final
HashMap
<
String
,
Object
>
map
=
New
.
hashMap
();
/**
* The current locale.
*/
Locale
locale
;
/**
* The currently executing statement.
*/
Statement
executingStatement
;
/**
* The current updatable result set.
*/
ResultSet
result
;
private
final
WebServer
server
;
private
final
ArrayList
<
String
>
commandHistory
;
private
Connection
conn
;
private
DatabaseMetaData
meta
;
private
DbContents
contents
=
new
DbContents
();
private
Bnf
bnf
;
private
boolean
shutdownServerOnDisconnect
;
WebSession
(
WebServer
server
)
{
this
.
server
=
server
;
// This must be stored in the session rather than in the server.
// Otherwise, one client could allow
// saving history for others (insecure).
this
.
commandHistory
=
server
.
getCommandHistoryList
();
}
/**
* Put an attribute value in the map.
*
* @param key the key
* @param value the new value
*/
void
put
(
String
key
,
Object
value
)
{
map
.
put
(
key
,
value
);
}
/**
* Get the value for the given key.
*
* @param key the key
* @return the value
*/
Object
get
(
String
key
)
{
if
(
"sessions"
.
equals
(
key
))
{
return
server
.
getSessions
();
}
return
map
.
get
(
key
);
}
/**
* Remove a session attribute from the map.
*
* @param key the key
*/
void
remove
(
String
key
)
{
map
.
remove
(
key
);
}
/**
* Get the BNF object.
*
* @return the BNF object
*/
Bnf
getBnf
()
{
return
bnf
;
}
/**
* Load the SQL grammar BNF.
*/
void
loadBnf
()
{
try
{
Bnf
newBnf
=
Bnf
.
getInstance
(
null
);
DbContextRule
columnRule
=
new
DbContextRule
(
contents
,
DbContextRule
.
COLUMN
);
DbContextRule
newAliasRule
=
new
DbContextRule
(
contents
,
DbContextRule
.
NEW_TABLE_ALIAS
);
DbContextRule
aliasRule
=
new
DbContextRule
(
contents
,
DbContextRule
.
TABLE_ALIAS
);
DbContextRule
tableRule
=
new
DbContextRule
(
contents
,
DbContextRule
.
TABLE
);
DbContextRule
schemaRule
=
new
DbContextRule
(
contents
,
DbContextRule
.
SCHEMA
);
DbContextRule
columnAliasRule
=
new
DbContextRule
(
contents
,
DbContextRule
.
COLUMN_ALIAS
);
DbContextRule
procedure
=
new
DbContextRule
(
contents
,
DbContextRule
.
PROCEDURE
);
newBnf
.
updateTopic
(
"procedure"
,
procedure
);
newBnf
.
updateTopic
(
"column_name"
,
columnRule
);
newBnf
.
updateTopic
(
"new_table_alias"
,
newAliasRule
);
newBnf
.
updateTopic
(
"table_alias"
,
aliasRule
);
newBnf
.
updateTopic
(
"column_alias"
,
columnAliasRule
);
newBnf
.
updateTopic
(
"table_name"
,
tableRule
);
newBnf
.
updateTopic
(
"schema_name"
,
schemaRule
);
newBnf
.
linkStatements
();
bnf
=
newBnf
;
}
catch
(
Exception
e
)
{
// ok we don't have the bnf
server
.
traceError
(
e
);
}
}
/**
* Get the SQL statement from history.
*
* @param id the history id
* @return the SQL statement
*/
String
getCommand
(
int
id
)
{
return
commandHistory
.
get
(
id
);
}
/**
* Add a SQL statement to the history.
*
* @param sql the SQL statement
*/
void
addCommand
(
String
sql
)
{
if
(
sql
==
null
)
{
return
;
}
sql
=
sql
.
trim
();
if
(
sql
.
length
()
==
0
)
{
return
;
}
if
(
commandHistory
.
size
()
>
MAX_HISTORY
)
{
commandHistory
.
remove
(
0
);
}
int
idx
=
commandHistory
.
indexOf
(
sql
);
if
(
idx
>=
0
)
{
commandHistory
.
remove
(
idx
);
}
commandHistory
.
add
(
sql
);
if
(
server
.
isCommandHistoryAllowed
())
{
server
.
saveCommandHistoryList
(
commandHistory
);
}
}
/**
* Get the list of SQL statements in the history.
*
* @return the commands
*/
ArrayList
<
String
>
getCommandHistory
()
{
return
commandHistory
;
}
/**
* Update session meta data information and get the information in a map.
*
* @return a map containing the session meta data
*/
HashMap
<
String
,
Object
>
getInfo
()
{
HashMap
<
String
,
Object
>
m
=
New
.
hashMap
();
m
.
putAll
(
map
);
m
.
put
(
"lastAccess"
,
new
Timestamp
(
lastAccess
).
toString
());
try
{
m
.
put
(
"url"
,
conn
==
null
?
"${text.admin.notConnected}"
:
conn
.
getMetaData
().
getURL
());
m
.
put
(
"user"
,
conn
==
null
?
"-"
:
conn
.
getMetaData
().
getUserName
());
m
.
put
(
"lastQuery"
,
commandHistory
.
size
()
==
0
?
""
:
commandHistory
.
get
(
0
));
m
.
put
(
"executing"
,
executingStatement
==
null
?
"${text.admin.no}"
:
"${text.admin.yes}"
);
}
catch
(
SQLException
e
)
{
DbException
.
traceThrowable
(
e
);
}
return
m
;
}
void
setConnection
(
Connection
conn
)
throws
SQLException
{
this
.
conn
=
conn
;
if
(
conn
==
null
)
{
meta
=
null
;
}
else
{
meta
=
conn
.
getMetaData
();
}
contents
=
new
DbContents
();
}
DatabaseMetaData
getMetaData
()
{
return
meta
;
}
Connection
getConnection
()
{
return
conn
;
}
DbContents
getContents
()
{
return
contents
;
}
/**
* Shutdown the server when disconnecting.
*/
void
setShutdownServerOnDisconnect
()
{
this
.
shutdownServerOnDisconnect
=
true
;
}
boolean
getShutdownServerOnDisconnect
()
{
return
shutdownServerOnDisconnect
;
}
/**
* Close the connection and stop the statement if one is currently
* executing.
*/
void
close
()
{
if
(
executingStatement
!=
null
)
{
try
{
executingStatement
.
cancel
();
}
catch
(
Exception
e
)
{
// ignore
}
}
if
(
conn
!=
null
)
{
try
{
conn
.
close
();
}
catch
(
Exception
e
)
{
// ignore
}
}
}
}
\ No newline at end of file
grog-webapp/src/main/java/org/legrog/util/WebThread.java
deleted
100644 → 0
View file @
e8aef6f
package
org
.
legrog
.
util
;
// Code copied from org.h2.server.web.WebThread
/*
* Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
//package org.h2.server.web;
import
java.io.BufferedInputStream
;
import
java.io.BufferedOutputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.OutputStream
;
import
java.net.Socket
;
import
java.net.UnknownHostException
;
import
java.util.Iterator
;
import
java.util.Locale
;
import
java.util.Properties
;
import
java.util.StringTokenizer
;
import
org.h2.engine.Constants
;
import
org.h2.engine.SysProperties
;
import
org.h2.message.DbException
;
import
org.h2.mvstore.DataUtils
;
import
org.h2.util.IOUtils
;
import
org.h2.util.NetUtils
;
import
org.h2.util.StringUtils
;
//import org.h2.server.web.*;
/**
* For each connection to a session, an object of this class is created.
* This class is used by the H2 Console.
*/
class
WebThread
extends
WebApp
implements
Runnable
{
protected
OutputStream
output
;
protected
final
Socket
socket
;
private
final
Thread
thread
;
private
InputStream
input
;
private
String
ifModifiedSince
;
WebThread
(
Socket
socket
,
WebServer
server
)
{
super
(
server
);
this
.
socket
=
socket
;
thread
=
new
Thread
(
this
,
"H2 Console thread"
);
}
/**
* Start the thread.
*/
void
start
()
{
thread
.
start
();
}
/**
* Wait until the thread is stopped.
*
* @param millis the maximum number of milliseconds to wait
*/
void
join
(
int
millis
)
throws
InterruptedException
{
thread
.
join
(
millis
);
}
/**
* Close the connection now.
*/
void
stopNow
()
{
this
.
stop
=
true
;
try
{
socket
.
close
();
}
catch
(
IOException
e
)
{
// ignore
}
}
private
String
getAllowedFile
(
String
requestedFile
)
{
if
(!
allow
())
{
return
"notAllowed.jsp"
;
}
if
(
requestedFile
.
length
()
==
0
)
{
return
"index.do"
;
}
return
requestedFile
;
}
@Override
public
void
run
()
{
try
{
input
=
new
BufferedInputStream
(
socket
.
getInputStream
());
output
=
new
BufferedOutputStream
(
socket
.
getOutputStream
());
while
(!
stop
)
{
if
(!
process
())
{
break
;
}
}
}
catch
(
Exception
e
)
{
DbException
.
traceThrowable
(
e
);
}
IOUtils
.
closeSilently
(
output
);
IOUtils
.
closeSilently
(
input
);
try
{
socket
.
close
();
}
catch
(
IOException
e
)
{
// ignore
}
finally
{
server
.
remove
(
this
);
}
}
@SuppressWarnings
(
"unchecked"
)
private
boolean
process
()
throws
IOException
{
boolean
keepAlive
=
false
;
String
head
=
readHeaderLine
();
if
(
head
.
startsWith
(
"GET "
)
||
head
.
startsWith
(
"POST "
))
{
int
begin
=
head
.
indexOf
(
'/'
),
end
=
head
.
lastIndexOf
(
' '
);
String
file
;
if
(
begin
<
0
||
end
<
begin
)
{
file
=
""
;
}
else
{
file
=
head
.
substring
(
begin
+
1
,
end
).
trim
();
}
trace
(
head
+
": "
+
file
);
file
=
getAllowedFile
(
file
);
attributes
=
new
Properties
();
int
paramIndex
=
file
.
indexOf
(
"?"
);
session
=
null
;
if
(
paramIndex
>=
0
)
{
String
attrib
=
file
.
substring
(
paramIndex
+
1
);
parseAttributes
(
attrib
);
String
sessionId
=
attributes
.
getProperty
(
"jsessionid"
);
file
=
file
.
substring
(
0
,
paramIndex
);
session
=
server
.
getSession
(
sessionId
);
}
keepAlive
=
parseHeader
();
String
hostAddr
=
socket
.
getInetAddress
().
getHostAddress
();
file
=
processRequest
(
file
,
hostAddr
);
if
(
file
.
length
()
==
0
)
{
// asynchronous request
return
true
;
}
String
message
;
byte
[]
bytes
;
if
(
cache
&&
ifModifiedSince
!=
null
&&
ifModifiedSince
.
equals
(
server
.
getStartDateTime
()))
{
bytes
=
null
;
message
=
"HTTP/1.1 304 Not Modified\r\n"
;
}
else
{
bytes
=
server
.
getFile
(
file
);
if
(
bytes
==
null
)
{
message
=
"HTTP/1.1 404 Not Found\r\n"
;
bytes
=
(
"File not found: "
+
file
).
getBytes
(
Constants
.
UTF8
);
message
+=
"Content-Length: "
+
bytes
.
length
+
"\r\n"
;
}
else
{
if
(
session
!=
null
&&
file
.
endsWith
(
".jsp"
))
{
String
page
=
new
String
(
bytes
,
Constants
.
UTF8
);
if
(
SysProperties
.
CONSOLE_STREAM
)
{
Iterator
<
String
>
it
=
(
Iterator
<
String
>)
session
.
map
.
remove
(
"chunks"
);
if
(
it
!=
null
)
{
message
=
"HTTP/1.1 200 OK\r\n"
;
message
+=
"Content-Type: "
+
mimeType
+
"\r\n"
;
message
+=
"Cache-Control: no-cache\r\n"
;
message
+=
"Transfer-Encoding: chunked\r\n"
;
message
+=
"\r\n"
;
trace
(
message
);
output
.
write
(
message
.
getBytes
());
while
(
it
.
hasNext
())
{
String
s
=
it
.
next
();
s
=
PageParser
.
parse
(
s
,
session
.
map
);
bytes
=
s
.
getBytes
(
Constants
.
UTF8
);
if
(
bytes
.
length
==
0
)
{
continue
;
}
output
.
write
(
Integer
.
toHexString
(
bytes
.
length
).
getBytes
());
output
.
write
(
"\r\n"
.
getBytes
());
output
.
write
(
bytes
);
output
.
write
(
"\r\n"
.
getBytes
());
output
.
flush
();
}
output
.
write
(
"0\r\n\r\n"
.
getBytes
());
output
.
flush
();
return
keepAlive
;
}
}
page
=
PageParser
.
parse
(
page
,
session
.
map
);
bytes
=
page
.
getBytes
(
Constants
.
UTF8
);
}
message
=
"HTTP/1.1 200 OK\r\n"
;
message
+=
"Content-Type: "
+
mimeType
+
"\r\n"
;
if
(!
cache
)
{
message
+=
"Cache-Control: no-cache\r\n"
;
}
else
{
message
+=
"Cache-Control: max-age=10\r\n"
;
message
+=
"Last-Modified: "
+
server
.
getStartDateTime
()
+
"\r\n"
;
}
message
+=
"Content-Length: "
+
bytes
.
length
+
"\r\n"
;
}
}
message
+=
"\r\n"
;
trace
(
message
);
output
.
write
(
message
.
getBytes
());
if
(
bytes
!=
null
)
{
output
.
write
(
bytes
);
}
output
.
flush
();
}
return
keepAlive
;
}
private
String
readHeaderLine
()
throws
IOException
{
StringBuilder
buff
=
new
StringBuilder
();
while
(
true
)
{
int
c
=
input
.
read
();
if
(
c
==
-
1
)
{
throw
new
IOException
(
"Unexpected EOF"
);
}
else
if
(
c
==
'\r'
)
{
if
(
input
.
read
()
==
'\n'
)
{
return
buff
.
length
()
>
0
?
buff
.
toString
()
:
null
;
}
}
else
if
(
c
==
'\n'
)
{
return
buff
.
length
()
>
0
?
buff
.
toString
()
:
null
;
}
else
{
buff
.
append
((
char
)
c
);
}
}
}
private
void
parseAttributes
(
String
s
)
{
trace
(
"data="
+
s
);
while
(
s
!=
null
)
{
int
idx
=
s
.
indexOf
(
'='
);
if
(
idx
>=
0
)
{
String
property
=
s
.
substring
(
0
,
idx
);
s
=
s
.
substring
(
idx
+
1
);
idx
=
s
.
indexOf
(
'&'
);
String
value
;
if
(
idx
>=
0
)
{
value
=
s
.
substring
(
0
,
idx
);
s
=
s
.
substring
(
idx
+
1
);
}
else
{
value
=
s
;
}
String
attr
=
StringUtils
.
urlDecode
(
value
);
attributes
.
put
(
property
,
attr
);
}
else
{
break
;
}
}
trace
(
attributes
.
toString
());
}
private
boolean
parseHeader
()
throws
IOException
{
boolean
keepAlive
=
false
;
trace
(
"parseHeader"
);
int
len
=
0
;
ifModifiedSince
=
null
;
boolean
multipart
=
false
;
while
(
true
)
{
String
line
=
readHeaderLine
();
if
(
line
==
null
)
{
break
;
}
trace
(
" "
+
line
);
String
lower
=
StringUtils
.
toLowerEnglish
(
line
);
if
(
lower
.
startsWith
(
"if-modified-since"
))
{
ifModifiedSince
=
getHeaderLineValue
(
line
);
}
else
if
(
lower
.
startsWith
(
"connection"
))
{
String
conn
=
getHeaderLineValue
(
line
);
if
(
"keep-alive"
.
equals
(
conn
))
{
keepAlive
=
true
;
}
}
else
if
(
lower
.
startsWith
(
"content-type"
))
{
String
type
=
getHeaderLineValue
(
line
);
if
(
type
.
startsWith
(
"multipart/form-data"
))
{
multipart
=
true
;
}
}
else
if
(
lower
.
startsWith
(
"content-length"
))
{
len
=
Integer
.
parseInt
(
getHeaderLineValue
(
line
));
trace
(
"len="
+
len
);
}
else
if
(
lower
.
startsWith
(
"user-agent"
))
{
boolean
isWebKit
=
lower
.
contains
(
"webkit/"
);
if
(
isWebKit
&&
session
!=
null
)
{
// workaround for what seems to be a WebKit bug:
// http://code.google.com/p/chromium/issues/detail?id=6402
session
.
put
(
"frame-border"
,
"1"
);
session
.
put
(
"frameset-border"
,
"2"
);
}
}
else
if
(
lower
.
startsWith
(
"accept-language"
))
{
Locale
locale
=
session
==
null
?
null
:
session
.
locale
;
if
(
locale
==
null
)
{
String
languages
=
getHeaderLineValue
(
line
);
StringTokenizer
tokenizer
=
new
StringTokenizer
(
languages
,
",;"
);
while
(
tokenizer
.
hasMoreTokens
())
{
String
token
=
tokenizer
.
nextToken
();
if
(!
token
.
startsWith
(
"q="
))
{
if
(
server
.
supportsLanguage
(
token
))
{
int
dash
=
token
.
indexOf
(
'-'
);
if
(
dash
>=
0
)
{
String
language
=
token
.
substring
(
0
,
dash
);
String
country
=
token
.
substring
(
dash
+
1
);
locale
=
new
Locale
(
language
,
country
);
}
else
{
locale
=
new
Locale
(
token
,
""
);
}
headerLanguage
=
locale
.
getLanguage
();
if
(
session
!=
null
)
{
session
.
locale
=
locale
;
session
.
put
(
"language"
,
headerLanguage
);
server
.
readTranslations
(
session
,
headerLanguage
);
}
break
;
}
}
}
}
}
else
if
(
line
.
trim
().
length
()
==
0
)
{
break
;
}
}
if
(
multipart
)
{
// not supported
}
else
if
(
session
!=
null
&&
len
>
0
)
{
byte
[]
bytes
=
DataUtils
.
newBytes
(
len
);
for
(
int
pos
=
0
;
pos
<
len
;)
{
pos
+=
input
.
read
(
bytes
,
pos
,
len
-
pos
);
}
String
s
=
new
String
(
bytes
);
parseAttributes
(
s
);
}
return
keepAlive
;
}
private
static
String
getHeaderLineValue
(
String
line
)
{
return
line
.
substring
(
line
.
indexOf
(
':'
)
+
1
).
trim
();
}
@Override
protected
String
adminShutdown
()
{
stopNow
();
return
super
.
adminShutdown
();
}
private
boolean
allow
()
{
if
(
server
.
getAllowOthers
())
{
return
true
;
}
try
{
return
NetUtils
.
isLocalAddress
(
socket
);
}
catch
(
UnknownHostException
e
)
{
server
.
traceError
(
e
);
return
false
;
}
}
private
void
trace
(
String
s
)
{
server
.
trace
(
s
);
}
}
\ No newline at end of file
Please
register
or
login
to post a comment