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 while running code coverage for " + pathList + " ." ;
185
+ final String msg = "Error while opening code coverage HTML 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
}
0 commit comments