Skip to content

Commit ac2b269

Browse files
Merge pull request #5366 from apache/delivery
Sync delivery to release170 for 17-rc3
2 parents 6d082ad + ba163d8 commit ac2b269

File tree

38 files changed

+786
-224
lines changed

38 files changed

+786
-224
lines changed

enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/actions/AddADBAction.java

Lines changed: 90 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,18 @@
2121
import com.oracle.bmc.model.BmcException;
2222
import java.awt.event.ActionEvent;
2323
import java.awt.event.ActionListener;
24+
import java.io.IOException;
2425
import java.util.ArrayList;
26+
import java.util.HashMap;
2527
import java.util.List;
28+
import java.util.Map;
2629
import java.util.Optional;
2730
import java.util.logging.Level;
2831
import java.util.logging.Logger;
2932
import java.util.stream.Collectors;
3033
import org.netbeans.modules.cloud.oracle.OCIManager;
3134
import org.netbeans.modules.cloud.oracle.OCIProfile;
35+
import org.netbeans.modules.cloud.oracle.actions.DownloadWalletDialog.WalletInfo;
3236
import org.netbeans.modules.cloud.oracle.compartment.CompartmentItem;
3337
import org.netbeans.modules.cloud.oracle.compartment.CompartmentNode;
3438
import org.netbeans.modules.cloud.oracle.database.DatabaseItem;
@@ -38,11 +42,14 @@
3842
import org.openide.DialogDescriptor;
3943
import org.openide.DialogDisplayer;
4044
import org.openide.NotifyDescriptor;
45+
import org.openide.NotifyDescriptor.ComposedInput.Callback;
46+
import org.openide.NotifyDescriptor.QuickPick;
4147
import org.openide.NotifyDescriptor.QuickPick.Item;
4248
import org.openide.awt.ActionID;
4349
import org.openide.awt.ActionReference;
4450
import org.openide.awt.ActionReferences;
4551
import org.openide.awt.ActionRegistration;
52+
import org.openide.util.Exceptions;
4653
import org.openide.util.NbBundle;
4754

4855
/**
@@ -65,80 +72,109 @@
6572
"AddADB=Add Oracle Autonomous DB",
6673
"SelectTenancy=Select Tenancy",
6774
"SelectCompartment=Select Compartment",
68-
"SelectDatabase=Select Database"
75+
"SelectDatabase=Select Compartment or Database",
76+
"EnterUsername=Enter Username",
77+
"EnterPassword=Enter Password"
6978
})
7079
public class AddADBAction implements ActionListener {
7180
private static final Logger LOGGER = Logger.getLogger(AddADBAction.class.getName());
7281

82+
private static final String DB = "db"; //NOI18N
83+
private static final String USERNAME = "username"; //NOI18N
84+
private static final String PASSWORD = "password"; //NOI18N
7385

7486
@Override
7587
public void actionPerformed(ActionEvent e) {
76-
List<TenancyItem> tenancies = new ArrayList<>();
77-
for (OCIProfile p : OCIManager.getDefault().getConnectedProfiles()) {
78-
p.getTenancy().ifPresent(tenancies::add);
79-
}
80-
Optional<TenancyItem> selectedTenancy = chooseOneItem(tenancies, Bundle.SelectTenancy());
81-
82-
Optional<CompartmentItem> selectedCompartment = Optional.empty();
83-
84-
if (!selectedTenancy.isPresent()) {
85-
return;
86-
}
87-
88-
List<CompartmentItem> compartments = CompartmentNode.getCompartments().apply(selectedTenancy.get());
89-
selectedCompartment = chooseOneItem(compartments, Bundle.SelectCompartment());
90-
DatabaseItem selectedDatabase = null;
88+
Map<String, Object> result = new HashMap<> ();
9189

92-
if (selectedCompartment.isPresent()) {
93-
while(selectedDatabase == null) {
94-
OCIItem item = chooseCopartmentOrDb(selectedCompartment.get());
95-
if (item == null) {
96-
return;
97-
}
98-
if (item instanceof DatabaseItem) {
99-
selectedDatabase = (DatabaseItem) item;
100-
}
101-
if (item instanceof CompartmentItem) {
102-
selectedCompartment = Optional.of((CompartmentItem) item);
90+
NotifyDescriptor.ComposedInput ci = new NotifyDescriptor.ComposedInput(Bundle.AddADB(), 3, new Callback() {
91+
Map<Integer, List> values = new HashMap<> ();
92+
93+
@Override
94+
public NotifyDescriptor createInput(NotifyDescriptor.ComposedInput input, int number) {
95+
if (number == 1) {
96+
List<TenancyItem> tenancies = new ArrayList<>();
97+
for (OCIProfile p : OCIManager.getDefault().getConnectedProfiles()) {
98+
p.getTenancy().ifPresent(tenancies::add);
99+
}
100+
String title;
101+
if (tenancies.size() == 1) {
102+
values.put(1, getCompartmentsAndDbs(tenancies.get(0)));
103+
title = Bundle.SelectCompartment();
104+
} else {
105+
values.put(1, tenancies);
106+
title = Bundle.SelectTenancy();
107+
}
108+
return createQuickPick(values.get(1), title);
109+
} else {
110+
NotifyDescriptor prev = input.getInputs()[number - 2];
111+
OCIItem prevItem = null;
112+
if (prev instanceof NotifyDescriptor.QuickPick) {
113+
Optional<String> selected = ((QuickPick) prev).getItems().stream().filter(item -> item.isSelected()).map(item -> item.getLabel()).findFirst();
114+
if (selected.isPresent()) {
115+
Optional<? extends OCIItem> ti = values.get(number - 1).stream().filter(t -> ((OCIItem) t).getName().equals(selected.get())).findFirst();
116+
if (ti.isPresent()) {
117+
prevItem = ti.get();
118+
}
119+
}
120+
if (prevItem instanceof DatabaseItem) {
121+
result.put(DB, prevItem);
122+
return new NotifyDescriptor.InputLine(Bundle.EnterUsername(), Bundle.EnterUsername());
123+
}
124+
values.put(number, getCompartmentsAndDbs(prevItem));
125+
input.setEstimatedNumberOfInputs(input.getEstimatedNumberOfInputs() + 1);
126+
return createQuickPick(values.get(number), Bundle.SelectDatabase());
127+
} else if (prev instanceof NotifyDescriptor.PasswordLine) {
128+
result.put(PASSWORD, ((NotifyDescriptor.PasswordLine) prev).getInputText());
129+
return null;
130+
} else if (prev instanceof NotifyDescriptor.InputLine) {
131+
String username = ((NotifyDescriptor.InputLine) prev).getInputText();
132+
if (username == null || username.trim().isEmpty()) {
133+
return prev;
134+
}
135+
result.put(USERNAME, username);
136+
return new NotifyDescriptor.PasswordLine(Bundle.EnterPassword(), Bundle.EnterPassword());
137+
}
138+
return null;
103139
}
104140
}
105-
}
106-
if (selectedDatabase != null) {
107-
DownloadWalletAction action = new DownloadWalletAction(selectedDatabase);
108-
action.actionPerformed(null);
141+
142+
});
143+
if (DialogDescriptor.OK_OPTION == DialogDisplayer.getDefault().notify(ci)) {
144+
try {
145+
DatabaseItem selectedDatabase = (DatabaseItem) result.get(DB);
146+
DownloadWalletAction action = new DownloadWalletAction(selectedDatabase);
147+
WalletInfo info = new WalletInfo(
148+
DownloadWalletDialog.getWalletsDir().getAbsolutePath(),
149+
AbstractPasswordPanel.generatePassword(),
150+
(String) result.get(USERNAME),
151+
((String) result.get(PASSWORD)).toCharArray());
152+
action.addConnection(info);
153+
} catch (IOException ex) {
154+
Exceptions.printStackTrace(ex);
155+
}
109156
}
110157
}
111158

112-
private <T extends OCIItem> Optional<T> chooseOneItem(List<T> ociItems, String title) {
113-
Optional<T> result = Optional.empty();
114-
if (ociItems.size() == 1) {
115-
result = Optional.of(ociItems.get(0));
116-
} else if (ociItems.size() > 0) {
117-
List<Item> items = ociItems.stream()
118-
.map(tenancy -> new Item(tenancy.getName(), tenancy.getDescription()))
119-
.collect(Collectors.toList());
120-
NotifyDescriptor.QuickPick qp = new NotifyDescriptor.QuickPick(title, title, items, false);
121-
if (DialogDescriptor.OK_OPTION == DialogDisplayer.getDefault().notify(qp)) {
122-
Optional<String> selected = qp.getItems().stream().filter(item -> item.isSelected()).map(item -> item.getLabel()).findFirst();
123-
if (selected.isPresent()) {
124-
result = ociItems.stream().filter(t -> t.getName().equals(selected.get())).findFirst();
125-
}
126-
127-
}
128-
}
129-
return result;
159+
private <T extends OCIItem> NotifyDescriptor.QuickPick createQuickPick(List<T> ociItems, String title) {
160+
161+
List<Item> items = ociItems.stream()
162+
.map(tenancy -> new Item(tenancy.getName(), tenancy.getDescription()))
163+
.collect(Collectors.toList());
164+
return new NotifyDescriptor.QuickPick(title, title, items, false);
130165
}
131166

132-
133-
private OCIItem chooseCopartmentOrDb(CompartmentItem compartment) {
167+
private List<OCIItem> getCompartmentsAndDbs(OCIItem parent) {
134168
List<OCIItem> items = new ArrayList<> ();
135169
try {
136-
items.addAll(DatabaseNode.getDatabases().apply(compartment));
170+
if (parent instanceof CompartmentItem) {
171+
items.addAll(DatabaseNode.getDatabases().apply((CompartmentItem) parent));
172+
}
137173
} catch (BmcException e) {
138174
LOGGER.log(Level.SEVERE, "Unable to load compartment list", e); // NOI18N
139175
}
140-
items.addAll(CompartmentNode.getCompartments().apply(compartment));
141-
return chooseOneItem(items, Bundle.SelectDatabase()).orElseGet(() -> null);
176+
items.addAll(CompartmentNode.getCompartments().apply(parent));
177+
return items;
142178
}
143179

144180
}

enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/actions/DownloadWalletAction.java

Lines changed: 96 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,16 @@
1919
package org.netbeans.modules.cloud.oracle.actions;
2020

2121
import java.awt.event.ActionEvent;
22-
import java.awt.event.ActionListener;
2322
import java.io.IOException;
23+
import java.net.URL;
2424
import java.nio.file.Files;
2525
import java.nio.file.Path;
2626
import java.text.MessageFormat;
2727
import java.util.Collections;
2828
import java.util.List;
2929
import java.util.Optional;
30+
import java.util.logging.Level;
31+
import java.util.logging.Logger;
3032
import java.util.stream.Collectors;
3133
import javax.swing.AbstractAction;
3234
import javax.swing.Action;
@@ -45,6 +47,8 @@
4547
import org.openide.awt.ActionReferences;
4648
import org.openide.awt.ActionRegistration;
4749
import org.openide.awt.StatusDisplayer;
50+
import org.openide.filesystems.URLMapper;
51+
import org.openide.util.BaseUtilities;
4852
import org.openide.util.ContextAwareAction;
4953
import org.openide.util.Exceptions;
5054
import org.openide.util.Lookup;
@@ -58,8 +62,8 @@
5862
category = "Tools",
5963
id = "org.netbeans.modules.cloud.oracle.actions.DownloadWalletAction"
6064
)
61-
@ActionRegistration(
62-
displayName = "#CTL_DownloadWalletAction",
65+
@ActionRegistration(
66+
displayName = "#CTL_DownloadWalletAction",
6367
asynchronous = true,
6468
lazy = true
6569
)
@@ -72,11 +76,15 @@
7276
"CTL_DownloadWalletAction=Download Wallet",
7377
"MSG_WalletDownloaded=Database Wallet was downloaded to {0}",
7478
"MSG_WalletDownloadedPassword=Database Wallet was downloaded. \nGenerated wallet password is: {0}",
75-
"MSG_WalletNoConnection=Wallet doesn't contain any connection"
79+
"MSG_WalletNoConnection=Wallet doesn't contain any connection",
80+
"WARN_DriverWithoutJars=No matching JDBC drivers are configured with code location(s). Driver {0} will be associated with the connection, but the " +
81+
"connection may fail because driver's code is not loadable. Continue ?"
82+
7683
})
7784
public class DownloadWalletAction extends AbstractAction implements ContextAwareAction {
85+
private static final Logger LOG = Logger.getLogger(DownloadWalletAction.class.getName());
7886

79-
private static final String URL_TEMPLATE = "jdbc:oracle:thin:@{0}?TNS_ADMIN=\"{1}\""; //NOI18N
87+
private static final String URL_TEMPLATE = "jdbc:oracle:thin:@{0}?TNS_ADMIN={1}"; //NOI18N
8088
private final DatabaseItem context;
8189
private OCIProfile session;
8290

@@ -99,47 +107,95 @@ public Action createContextAwareInstance(Lookup actionContext) {
99107
@Override
100108
public void actionPerformed(ActionEvent ev) {
101109
Optional<DownloadWalletDialog.WalletInfo> result = DownloadWalletDialog.showDialog(context);
102-
result.ifPresent((p) -> {
103-
try {
104-
Path walletPath = session.downloadWallet(context, new String(p.getWalletPassword()), p.getPath());
105-
if (p.getDbUser() != null && p.getDbPassword() != null) {
106-
107-
JDBCDriver[] drivers = JDBCDriverManager.getDefault().getDrivers("oracle.jdbc.OracleDriver"); //NOI18N
108-
if (drivers.length > 0) {
109-
String connectionName = context.getConnectionName();
110-
if (connectionName == null) {
111-
Optional<String> n = parseConnectionNames(walletPath).stream().findFirst();
112-
if (n.isPresent()) {
113-
connectionName = n.get();
114-
} else {
115-
StatusDisplayer.getDefault().setStatusText(Bundle.MSG_WalletNoConnection());
116-
return;
117-
}
110+
result.ifPresent(p -> addConnection(p));
111+
}
112+
113+
void addConnection(DownloadWalletDialog.WalletInfo p) {
114+
try {
115+
Path walletPath = session.downloadWallet(context, new String(p.getWalletPassword()), p.getPath());
116+
if (p.getDbUser() != null && p.getDbPassword() != null) {
117+
118+
JDBCDriver[] drivers = JDBCDriverManager.getDefault().getDrivers("oracle.jdbc.OracleDriver"); //NOI18N
119+
JDBCDriver jarsPresent = null;
120+
121+
if (drivers.length > 0) {
122+
123+
// prefer a driver that actually defines some JARs.
124+
for (JDBCDriver d : drivers) {
125+
if (isAvailable(d)) {
126+
jarsPresent = d;
127+
break;
128+
}
129+
}
130+
if (jarsPresent == null) {
131+
jarsPresent = drivers[0];
132+
LOG.log(Level.WARNING, "Unable to find driver JARs for wallet {0}, using fallback driver: {1}", new Object[] { walletPath, jarsPresent.getName() });
133+
NotifyDescriptor.Confirmation msg = new NotifyDescriptor.Confirmation(Bundle.WARN_DriverWithoutJars(jarsPresent.getName()),
134+
NotifyDescriptor.WARNING_MESSAGE, NotifyDescriptor.YES_NO_OPTION);
135+
Object choice = DialogDisplayer.getDefault().notify(msg);
136+
if (choice != NotifyDescriptor.YES_OPTION && choice != NotifyDescriptor.OK_OPTION) {
137+
return;
138+
}
139+
}
140+
String connectionName = context.getConnectionName();
141+
if (connectionName == null) {
142+
Optional<String> n = parseConnectionNames(walletPath).stream().findFirst();
143+
if (n.isPresent()) {
144+
connectionName = n.get();
145+
} else {
146+
StatusDisplayer.getDefault().setStatusText(Bundle.MSG_WalletNoConnection());
147+
return;
118148
}
119-
String dbUrl = MessageFormat.format(URL_TEMPLATE, connectionName, walletPath);
120-
DatabaseConnection dbConn = DatabaseConnection.create(
121-
drivers[0],
122-
dbUrl,
123-
p.getDbUser(),
124-
p.getDbUser(),
125-
new String(p.getDbPassword()),
126-
true,
127-
context.getName());
128-
ConnectionManager.getDefault().addConnection(dbConn);
129149
}
130-
DialogDisplayer.getDefault().notifyLater(
131-
new NotifyDescriptor.Message(
132-
Bundle.MSG_WalletDownloadedPassword(
133-
new String(p.getWalletPassword()))));
134-
} else {
135-
StatusDisplayer.getDefault().setStatusText(Bundle.MSG_WalletDownloaded(walletPath.toString()));
150+
String dbUrl = MessageFormat.format(URL_TEMPLATE, connectionName, BaseUtilities.escapeParameters(new String[] { walletPath.toString() }));
151+
DatabaseConnection dbConn = DatabaseConnection.create(
152+
drivers[0],
153+
dbUrl,
154+
p.getDbUser(),
155+
p.getDbUser(),
156+
new String(p.getDbPassword()),
157+
true,
158+
context.getName());
159+
ConnectionManager.getDefault().addConnection(dbConn);
136160
}
137-
} catch (DatabaseException | IOException ex) {
138-
Exceptions.printStackTrace(ex);
161+
162+
// PENDING: what should happen, if the driver is not found at all - display an info message ?
163+
164+
DialogDisplayer.getDefault().notifyLater(
165+
new NotifyDescriptor.Message(
166+
Bundle.MSG_WalletDownloadedPassword(
167+
new String(p.getWalletPassword()))));
168+
} else {
169+
StatusDisplayer.getDefault().setStatusText(Bundle.MSG_WalletDownloaded(walletPath.toString()));
139170
}
140-
});
171+
} catch (DatabaseException | IOException ex) {
172+
Exceptions.printStackTrace(ex);
173+
}
141174
}
142175

176+
static boolean isAvailable(JDBCDriver driver) {
177+
URL[] urls = driver.getURLs();
178+
for (URL u : urls) {
179+
if (URLMapper.findFileObject(u) == null) {
180+
return false;
181+
}
182+
}
183+
if (urls.length > 0) {
184+
// true, some jar is defined && exists.
185+
return true;
186+
} else {
187+
// if the JDBC drive does not list jars, its class must be reachable. DbDriverManager uses no-arg classloader constructor, so it is
188+
// using systemClassLoader as a parent for no-URL URLClassloader.
189+
try {
190+
Class.forName(driver.getClassName(), true, ClassLoader.getSystemClassLoader());
191+
return true;
192+
} catch (ClassNotFoundException | SecurityException | LinkageError ex) {
193+
// expected, class is not avaialble
194+
return false;
195+
}
196+
}
197+
}
198+
143199
protected List<String> parseConnectionNames(Path wallet) {
144200
Path tns = wallet.resolve("tnsnames.ora"); //NOI18N
145201
try {

enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/actions/DownloadWalletDialog.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ protected void checkPassword() {
243243
checkPasswordLogic(passwd1, passwd2, (m) -> errorMessage(m));
244244
}
245245

246-
private static File getWalletsDir() throws IOException {
246+
static File getWalletsDir() throws IOException {
247247
FileObject fo = FileUtil.createFolder(FileUtil.getConfigRoot(), WALLETS_PATH);
248248
return FileUtil.toFile(fo);
249249
}

0 commit comments

Comments
 (0)