Skip to content

Commit

Permalink
Merge pull request #5366 from apache/delivery
Browse files Browse the repository at this point in the history
Sync delivery to release170 for 17-rc3
  • Loading branch information
neilcsmith-net authored Feb 1, 2023
2 parents 6d082ad + ba163d8 commit ac2b269
Show file tree
Hide file tree
Showing 38 changed files with 786 additions and 224 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,18 @@
import com.oracle.bmc.model.BmcException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import org.netbeans.modules.cloud.oracle.OCIManager;
import org.netbeans.modules.cloud.oracle.OCIProfile;
import org.netbeans.modules.cloud.oracle.actions.DownloadWalletDialog.WalletInfo;
import org.netbeans.modules.cloud.oracle.compartment.CompartmentItem;
import org.netbeans.modules.cloud.oracle.compartment.CompartmentNode;
import org.netbeans.modules.cloud.oracle.database.DatabaseItem;
Expand All @@ -38,11 +42,14 @@
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.NotifyDescriptor.ComposedInput.Callback;
import org.openide.NotifyDescriptor.QuickPick;
import org.openide.NotifyDescriptor.QuickPick.Item;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionReferences;
import org.openide.awt.ActionRegistration;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;

/**
Expand All @@ -65,80 +72,109 @@
"AddADB=Add Oracle Autonomous DB",
"SelectTenancy=Select Tenancy",
"SelectCompartment=Select Compartment",
"SelectDatabase=Select Database"
"SelectDatabase=Select Compartment or Database",
"EnterUsername=Enter Username",
"EnterPassword=Enter Password"
})
public class AddADBAction implements ActionListener {
private static final Logger LOGGER = Logger.getLogger(AddADBAction.class.getName());

private static final String DB = "db"; //NOI18N
private static final String USERNAME = "username"; //NOI18N
private static final String PASSWORD = "password"; //NOI18N

@Override
public void actionPerformed(ActionEvent e) {
List<TenancyItem> tenancies = new ArrayList<>();
for (OCIProfile p : OCIManager.getDefault().getConnectedProfiles()) {
p.getTenancy().ifPresent(tenancies::add);
}
Optional<TenancyItem> selectedTenancy = chooseOneItem(tenancies, Bundle.SelectTenancy());

Optional<CompartmentItem> selectedCompartment = Optional.empty();

if (!selectedTenancy.isPresent()) {
return;
}

List<CompartmentItem> compartments = CompartmentNode.getCompartments().apply(selectedTenancy.get());
selectedCompartment = chooseOneItem(compartments, Bundle.SelectCompartment());
DatabaseItem selectedDatabase = null;
Map<String, Object> result = new HashMap<> ();

if (selectedCompartment.isPresent()) {
while(selectedDatabase == null) {
OCIItem item = chooseCopartmentOrDb(selectedCompartment.get());
if (item == null) {
return;
}
if (item instanceof DatabaseItem) {
selectedDatabase = (DatabaseItem) item;
}
if (item instanceof CompartmentItem) {
selectedCompartment = Optional.of((CompartmentItem) item);
NotifyDescriptor.ComposedInput ci = new NotifyDescriptor.ComposedInput(Bundle.AddADB(), 3, new Callback() {
Map<Integer, List> values = new HashMap<> ();

@Override
public NotifyDescriptor createInput(NotifyDescriptor.ComposedInput input, int number) {
if (number == 1) {
List<TenancyItem> tenancies = new ArrayList<>();
for (OCIProfile p : OCIManager.getDefault().getConnectedProfiles()) {
p.getTenancy().ifPresent(tenancies::add);
}
String title;
if (tenancies.size() == 1) {
values.put(1, getCompartmentsAndDbs(tenancies.get(0)));
title = Bundle.SelectCompartment();
} else {
values.put(1, tenancies);
title = Bundle.SelectTenancy();
}
return createQuickPick(values.get(1), title);
} else {
NotifyDescriptor prev = input.getInputs()[number - 2];
OCIItem prevItem = null;
if (prev instanceof NotifyDescriptor.QuickPick) {
Optional<String> selected = ((QuickPick) prev).getItems().stream().filter(item -> item.isSelected()).map(item -> item.getLabel()).findFirst();
if (selected.isPresent()) {
Optional<? extends OCIItem> ti = values.get(number - 1).stream().filter(t -> ((OCIItem) t).getName().equals(selected.get())).findFirst();
if (ti.isPresent()) {
prevItem = ti.get();
}
}
if (prevItem instanceof DatabaseItem) {
result.put(DB, prevItem);
return new NotifyDescriptor.InputLine(Bundle.EnterUsername(), Bundle.EnterUsername());
}
values.put(number, getCompartmentsAndDbs(prevItem));
input.setEstimatedNumberOfInputs(input.getEstimatedNumberOfInputs() + 1);
return createQuickPick(values.get(number), Bundle.SelectDatabase());
} else if (prev instanceof NotifyDescriptor.PasswordLine) {
result.put(PASSWORD, ((NotifyDescriptor.PasswordLine) prev).getInputText());
return null;
} else if (prev instanceof NotifyDescriptor.InputLine) {
String username = ((NotifyDescriptor.InputLine) prev).getInputText();
if (username == null || username.trim().isEmpty()) {
return prev;
}
result.put(USERNAME, username);
return new NotifyDescriptor.PasswordLine(Bundle.EnterPassword(), Bundle.EnterPassword());
}
return null;
}
}
}
if (selectedDatabase != null) {
DownloadWalletAction action = new DownloadWalletAction(selectedDatabase);
action.actionPerformed(null);

});
if (DialogDescriptor.OK_OPTION == DialogDisplayer.getDefault().notify(ci)) {
try {
DatabaseItem selectedDatabase = (DatabaseItem) result.get(DB);
DownloadWalletAction action = new DownloadWalletAction(selectedDatabase);
WalletInfo info = new WalletInfo(
DownloadWalletDialog.getWalletsDir().getAbsolutePath(),
AbstractPasswordPanel.generatePassword(),
(String) result.get(USERNAME),
((String) result.get(PASSWORD)).toCharArray());
action.addConnection(info);
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
}
}

private <T extends OCIItem> Optional<T> chooseOneItem(List<T> ociItems, String title) {
Optional<T> result = Optional.empty();
if (ociItems.size() == 1) {
result = Optional.of(ociItems.get(0));
} else if (ociItems.size() > 0) {
List<Item> items = ociItems.stream()
.map(tenancy -> new Item(tenancy.getName(), tenancy.getDescription()))
.collect(Collectors.toList());
NotifyDescriptor.QuickPick qp = new NotifyDescriptor.QuickPick(title, title, items, false);
if (DialogDescriptor.OK_OPTION == DialogDisplayer.getDefault().notify(qp)) {
Optional<String> selected = qp.getItems().stream().filter(item -> item.isSelected()).map(item -> item.getLabel()).findFirst();
if (selected.isPresent()) {
result = ociItems.stream().filter(t -> t.getName().equals(selected.get())).findFirst();
}

}
}
return result;
private <T extends OCIItem> NotifyDescriptor.QuickPick createQuickPick(List<T> ociItems, String title) {

List<Item> items = ociItems.stream()
.map(tenancy -> new Item(tenancy.getName(), tenancy.getDescription()))
.collect(Collectors.toList());
return new NotifyDescriptor.QuickPick(title, title, items, false);
}


private OCIItem chooseCopartmentOrDb(CompartmentItem compartment) {
private List<OCIItem> getCompartmentsAndDbs(OCIItem parent) {
List<OCIItem> items = new ArrayList<> ();
try {
items.addAll(DatabaseNode.getDatabases().apply(compartment));
if (parent instanceof CompartmentItem) {
items.addAll(DatabaseNode.getDatabases().apply((CompartmentItem) parent));
}
} catch (BmcException e) {
LOGGER.log(Level.SEVERE, "Unable to load compartment list", e); // NOI18N
}
items.addAll(CompartmentNode.getCompartments().apply(compartment));
return chooseOneItem(items, Bundle.SelectDatabase()).orElseGet(() -> null);
items.addAll(CompartmentNode.getCompartments().apply(parent));
return items;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,16 @@
package org.netbeans.modules.cloud.oracle.actions;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.text.MessageFormat;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import javax.swing.AbstractAction;
import javax.swing.Action;
Expand All @@ -45,6 +47,8 @@
import org.openide.awt.ActionReferences;
import org.openide.awt.ActionRegistration;
import org.openide.awt.StatusDisplayer;
import org.openide.filesystems.URLMapper;
import org.openide.util.BaseUtilities;
import org.openide.util.ContextAwareAction;
import org.openide.util.Exceptions;
import org.openide.util.Lookup;
Expand All @@ -58,8 +62,8 @@
category = "Tools",
id = "org.netbeans.modules.cloud.oracle.actions.DownloadWalletAction"
)
@ActionRegistration(
displayName = "#CTL_DownloadWalletAction",
@ActionRegistration(
displayName = "#CTL_DownloadWalletAction",
asynchronous = true,
lazy = true
)
Expand All @@ -72,11 +76,15 @@
"CTL_DownloadWalletAction=Download Wallet",
"MSG_WalletDownloaded=Database Wallet was downloaded to {0}",
"MSG_WalletDownloadedPassword=Database Wallet was downloaded. \nGenerated wallet password is: {0}",
"MSG_WalletNoConnection=Wallet doesn't contain any connection"
"MSG_WalletNoConnection=Wallet doesn't contain any connection",
"WARN_DriverWithoutJars=No matching JDBC drivers are configured with code location(s). Driver {0} will be associated with the connection, but the " +
"connection may fail because driver's code is not loadable. Continue ?"

})
public class DownloadWalletAction extends AbstractAction implements ContextAwareAction {
private static final Logger LOG = Logger.getLogger(DownloadWalletAction.class.getName());

private static final String URL_TEMPLATE = "jdbc:oracle:thin:@{0}?TNS_ADMIN=\"{1}\""; //NOI18N
private static final String URL_TEMPLATE = "jdbc:oracle:thin:@{0}?TNS_ADMIN={1}"; //NOI18N
private final DatabaseItem context;
private OCIProfile session;

Expand All @@ -99,47 +107,95 @@ public Action createContextAwareInstance(Lookup actionContext) {
@Override
public void actionPerformed(ActionEvent ev) {
Optional<DownloadWalletDialog.WalletInfo> result = DownloadWalletDialog.showDialog(context);
result.ifPresent((p) -> {
try {
Path walletPath = session.downloadWallet(context, new String(p.getWalletPassword()), p.getPath());
if (p.getDbUser() != null && p.getDbPassword() != null) {

JDBCDriver[] drivers = JDBCDriverManager.getDefault().getDrivers("oracle.jdbc.OracleDriver"); //NOI18N
if (drivers.length > 0) {
String connectionName = context.getConnectionName();
if (connectionName == null) {
Optional<String> n = parseConnectionNames(walletPath).stream().findFirst();
if (n.isPresent()) {
connectionName = n.get();
} else {
StatusDisplayer.getDefault().setStatusText(Bundle.MSG_WalletNoConnection());
return;
}
result.ifPresent(p -> addConnection(p));
}

void addConnection(DownloadWalletDialog.WalletInfo p) {
try {
Path walletPath = session.downloadWallet(context, new String(p.getWalletPassword()), p.getPath());
if (p.getDbUser() != null && p.getDbPassword() != null) {

JDBCDriver[] drivers = JDBCDriverManager.getDefault().getDrivers("oracle.jdbc.OracleDriver"); //NOI18N
JDBCDriver jarsPresent = null;

if (drivers.length > 0) {

// prefer a driver that actually defines some JARs.
for (JDBCDriver d : drivers) {
if (isAvailable(d)) {
jarsPresent = d;
break;
}
}
if (jarsPresent == null) {
jarsPresent = drivers[0];
LOG.log(Level.WARNING, "Unable to find driver JARs for wallet {0}, using fallback driver: {1}", new Object[] { walletPath, jarsPresent.getName() });
NotifyDescriptor.Confirmation msg = new NotifyDescriptor.Confirmation(Bundle.WARN_DriverWithoutJars(jarsPresent.getName()),
NotifyDescriptor.WARNING_MESSAGE, NotifyDescriptor.YES_NO_OPTION);
Object choice = DialogDisplayer.getDefault().notify(msg);
if (choice != NotifyDescriptor.YES_OPTION && choice != NotifyDescriptor.OK_OPTION) {
return;
}
}
String connectionName = context.getConnectionName();
if (connectionName == null) {
Optional<String> n = parseConnectionNames(walletPath).stream().findFirst();
if (n.isPresent()) {
connectionName = n.get();
} else {
StatusDisplayer.getDefault().setStatusText(Bundle.MSG_WalletNoConnection());
return;
}
String dbUrl = MessageFormat.format(URL_TEMPLATE, connectionName, walletPath);
DatabaseConnection dbConn = DatabaseConnection.create(
drivers[0],
dbUrl,
p.getDbUser(),
p.getDbUser(),
new String(p.getDbPassword()),
true,
context.getName());
ConnectionManager.getDefault().addConnection(dbConn);
}
DialogDisplayer.getDefault().notifyLater(
new NotifyDescriptor.Message(
Bundle.MSG_WalletDownloadedPassword(
new String(p.getWalletPassword()))));
} else {
StatusDisplayer.getDefault().setStatusText(Bundle.MSG_WalletDownloaded(walletPath.toString()));
String dbUrl = MessageFormat.format(URL_TEMPLATE, connectionName, BaseUtilities.escapeParameters(new String[] { walletPath.toString() }));
DatabaseConnection dbConn = DatabaseConnection.create(
drivers[0],
dbUrl,
p.getDbUser(),
p.getDbUser(),
new String(p.getDbPassword()),
true,
context.getName());
ConnectionManager.getDefault().addConnection(dbConn);
}
} catch (DatabaseException | IOException ex) {
Exceptions.printStackTrace(ex);

// PENDING: what should happen, if the driver is not found at all - display an info message ?

DialogDisplayer.getDefault().notifyLater(
new NotifyDescriptor.Message(
Bundle.MSG_WalletDownloadedPassword(
new String(p.getWalletPassword()))));
} else {
StatusDisplayer.getDefault().setStatusText(Bundle.MSG_WalletDownloaded(walletPath.toString()));
}
});
} catch (DatabaseException | IOException ex) {
Exceptions.printStackTrace(ex);
}
}

static boolean isAvailable(JDBCDriver driver) {
URL[] urls = driver.getURLs();
for (URL u : urls) {
if (URLMapper.findFileObject(u) == null) {
return false;
}
}
if (urls.length > 0) {
// true, some jar is defined && exists.
return true;
} else {
// if the JDBC drive does not list jars, its class must be reachable. DbDriverManager uses no-arg classloader constructor, so it is
// using systemClassLoader as a parent for no-URL URLClassloader.
try {
Class.forName(driver.getClassName(), true, ClassLoader.getSystemClassLoader());
return true;
} catch (ClassNotFoundException | SecurityException | LinkageError ex) {
// expected, class is not avaialble
return false;
}
}
}

protected List<String> parseConnectionNames(Path wallet) {
Path tns = wallet.resolve("tnsnames.ora"); //NOI18N
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ protected void checkPassword() {
checkPasswordLogic(passwd1, passwd2, (m) -> errorMessage(m));
}

private static File getWalletsDir() throws IOException {
static File getWalletsDir() throws IOException {
FileObject fo = FileUtil.createFolder(FileUtil.getConfigRoot(), WALLETS_PATH);
return FileUtil.toFile(fo);
}
Expand Down
Loading

0 comments on commit ac2b269

Please sign in to comment.