22
22
import java .sql .Connection ;
23
23
import java .util .ArrayList ;
24
24
import java .util .Arrays ;
25
+ import java .util .HashMap ;
25
26
import java .util .List ;
27
+ import java .util .Map ;
26
28
import java .util .logging .Logger ;
29
+ import java .util .stream .Collectors ;
27
30
31
+ import org .utplsql .sqldev .dal .RealtimeReporterDao ;
28
32
import org .utplsql .sqldev .dal .UtplsqlDao ;
29
33
import org .utplsql .sqldev .exception .GenericDatabaseAccessException ;
30
34
import org .utplsql .sqldev .exception .GenericRuntimeException ;
31
35
import org .utplsql .sqldev .model .DatabaseTools ;
32
36
import org .utplsql .sqldev .model .FileTools ;
37
+ import org .utplsql .sqldev .model .preference .PreferenceModel ;
38
+ import org .utplsql .sqldev .runner .UtplsqlRunner ;
33
39
import org .utplsql .sqldev .ui .coverage .CodeCoverageReporterDialog ;
34
40
41
+ import oracle .ide .config .Preferences ;
42
+
35
43
public class CodeCoverageReporter {
36
44
private static final Logger logger =Logger .getLogger (CodeCoverageReporter .class .getName ());
37
45
46
+ private String connectionName ;
38
47
private Connection conn ;
39
48
private List <String >pathList ;
40
49
private List <String >includeObjectList ;
@@ -47,14 +56,17 @@ public CodeCoverageReporter(final List<String> pathList, final List<String> incl
47
56
final String connectionName ) {
48
57
this .pathList =pathList ;
49
58
this .includeObjectList =includeObjectList ;
59
+ setDefaultSchema ();
50
60
setConnection (connectionName );
51
61
}
52
62
63
+ // constructor for testing purposes only
53
64
public CodeCoverageReporter (final List <String >pathList ,final List <String >includeObjectList ,
54
65
final Connection conn ) {
55
66
this .pathList =pathList ;
56
67
this .includeObjectList =includeObjectList ;
57
68
this .conn =conn ;
69
+ setDefaultSchema ();
58
70
}
59
71
60
72
private void setConnection (final String connectionName ) {
@@ -64,7 +76,32 @@ private void setConnection(final String connectionName) {
64
76
throw new NullPointerException ();
65
77
}else {
66
78
// must be closed manually
67
- conn =DatabaseTools .cloneConnection (connectionName );
79
+ this .connectionName =connectionName ;
80
+ this .conn =DatabaseTools .getConnection (connectionName );
81
+ }
82
+ }
83
+
84
+ private void setDefaultSchema () {
85
+ if (includeObjectList !=null && !includeObjectList .isEmpty ()) {
86
+ // use the owner with the most hits in includeObjectList
87
+ HashMap <String ,Integer >owners =new HashMap <>();
88
+ for (String entry :includeObjectList ) {
89
+ String []obj =entry .toUpperCase ().split ("\\ ." );
90
+ if (obj .length ==2 ) {
91
+ // only if objectOwner and objectName are available
92
+ Integer count =owners .get (obj [0 ]);
93
+ if (count ==null ) {
94
+ count =1 ;
95
+ }else {
96
+ count ++;
97
+ }
98
+ owners .put (obj [0 ],count );
99
+ }
100
+ }
101
+ List <String >sortedOwners =owners .entrySet ().stream ()
102
+ .sorted (Map .Entry .<String ,Integer >comparingByValue ().reversed ()).map (Map .Entry ::getKey )
103
+ .collect (Collectors .toList ());
104
+ schemas =String .join (", " ,sortedOwners );
68
105
}
69
106
}
70
107
@@ -83,12 +120,57 @@ private ArrayList<String> toStringList(final String s) {
83
120
private void run () {
84
121
logger .fine (() ->"Running code coverage reporter for " +pathList +"..." );
85
122
try {
86
- final UtplsqlDao dal =new UtplsqlDao (conn );
87
- final String content =dal .htmlCodeCoverage (pathList ,toStringList (schemas ),
123
+ final RealtimeReporterDao dao =new RealtimeReporterDao (conn );
124
+ PreferenceModel preferences ;
125
+ try {
126
+ preferences =PreferenceModel .getInstance (Preferences .getPreferences ());
127
+ }catch (NoClassDefFoundError error ) {
128
+ // not running in SQL Developer (in tests)
129
+ preferences =PreferenceModel .getInstance (null );
130
+ }
131
+ if (preferences .isUseRealtimeReporter () &&dao .isSupported () &&connectionName !=null ) {
132
+ runCodeCoverageWithRealtimeReporter ();
133
+ }else {
134
+ runCodeCoverageStandalone ();
135
+ }
136
+ }finally {
137
+ if (frame !=null ) {
138
+ frame .exit ();
139
+ }
140
+ }
141
+ }
142
+
143
+ private void runCodeCoverageWithRealtimeReporter () {
144
+ final UtplsqlRunner runner =new UtplsqlRunner (pathList ,toStringList (schemas ),toStringList (includeObjects ),
145
+ toStringList (excludeObjects ),connectionName );
146
+ runner .runTestAsync ();
147
+ }
148
+
149
+ private void runCodeCoverageStandalone () {
150
+ Connection coverageConn =null ;
151
+ try {
152
+ coverageConn =conn !=null ?conn :DatabaseTools .cloneConnection (connectionName );
153
+ final UtplsqlDao dao =new UtplsqlDao (coverageConn );
154
+ final String html =dao .htmlCodeCoverage (pathList ,toStringList (schemas ),
88
155
toStringList (includeObjects ),toStringList (excludeObjects ));
156
+ openInBrowser (html );
157
+ }finally {
158
+ try {
159
+ if (coverageConn !=null &&conn ==null ) {
160
+ // close only if connection has been cloned
161
+ DatabaseTools .closeConnection (coverageConn );
162
+ }
163
+ }catch (GenericDatabaseAccessException e ) {
164
+ // ignore
165
+ }
166
+ }
167
+ }
168
+
169
+ public static void openInBrowser (String html ) {
170
+ try {
89
171
final File file =File .createTempFile ("utplsql_" ,".html" );
90
172
logger .fine (() ->"Writing result to " +file +"..." );
91
- FileTools .writeFile (file .toPath (),Arrays .asList (content .split (System .lineSeparator ())),StandardCharsets .UTF_8 );
173
+ FileTools .writeFile (file .toPath (),Arrays .asList (html .split (System .lineSeparator ())),StandardCharsets .UTF_8 );
92
174
final URL url =file .toURI ().toURL ();
93
175
logger .fine (() ->"Opening " +url .toExternalForm () +" in browser..." );
94
176
final Desktop desktop =Desktop .isDesktopSupported () ?Desktop .getDesktop () :null ;
@@ -97,21 +179,12 @@ private void run() {
97
179
logger .fine (() ->url .toExternalForm () +" opened in browser." );
98
180
}else {
99
181
logger .severe (
100
- () ->"Could not launch " +file +"in browser. No default browser defined on this system." );
182
+ () ->"Could not launch " +file +" in browser. No default browser defined on this system." );
101
183
}
102
184
}catch (Exception e ) {
103
- final String msg ="Error whilerunning code coveragefor " + pathList + " ." ;
185
+ final String msg ="Error whileopening code coverageHTML report in browser ." ;
104
186
logger .severe (() ->msg );
105
187
throw new GenericRuntimeException (msg ,e );
106
- }finally {
107
- try {
108
- DatabaseTools .closeConnection (conn );
109
- }catch (GenericDatabaseAccessException e ) {
110
- // ignore
111
- }
112
- if (frame !=null ) {
113
- frame .exit ();
114
- }
115
188
}
116
189
}
117
190
@@ -143,6 +216,10 @@ public void setSchemas(final String schemas) {
143
216
this .schemas =schemas ;
144
217
}
145
218
219
+ public String getSchemas () {
220
+ return schemas ;
221
+ }
222
+
146
223
public void setIncludeObjects (final String includeObjects ) {
147
224
this .includeObjects =includeObjects ;
148
225
}