From 59b4b3dc53dcc4c642bf7ff98a13764eab69cee0 Mon Sep 17 00:00:00 2001 From: Sonia Zorba <zorba@oats.inaf.it> Date: Wed, 26 Jul 2017 00:07:11 +0200 Subject: [PATCH] Credentials insertion and management changes --- .../main/java/it/inaf/ia2/tsm/TapSchema.java | 3 - .../it/inaf/ia2/tsm/datalayer/DBBroker.java | 4 +- .../ia2/tsm/webapp/ConfigurationManager.java | 56 +++- .../ia2/tsm/webapp/ConsistencyChecksBean.java | 2 +- .../ia2/tsm/webapp/CredentialsEditing.java | 143 ++++---- .../ia2/tsm/webapp/SchemaSelectionBean.java | 311 ------------------ .../ia2/tsm/webapp/TapSchemaEditingBean.java | 34 +- .../inaf/ia2/tsm/webapp/TapSchemaLoader.java | 172 ++++++++++ .../tsm/webapp/TapSchemaLoaderResource.java | 8 +- .../it/inaf/ia2/tsm/webapp/UsersEditing.java | 9 +- .../env/CustomPartialResponseWriter.java | 14 +- .../ia2/tsm/webapp/env/JSUpdateHandler.java | 32 -- .../it/inaf/ia2/tsm/webapp/env/UIModal.java | 71 ---- .../src/main/webapp/credentialsEditing.xhtml | 171 ++++++---- .../main/webapp/resources/js/async-loader.js | 14 +- .../src/main/webapp/resources/js/common.js | 3 +- .../main/webapp/resources/js/credentials.js | 28 +- .../tsm_components/print_credentials.xhtml | 12 + .../src/main/webapp/schemaSelection.xhtml | 127 ------- .../src/main/webapp/tapSchemaEditing.xhtml | 4 +- 20 files changed, 447 insertions(+), 771 deletions(-) delete mode 100644 TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/SchemaSelectionBean.java create mode 100644 TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/TapSchemaLoader.java delete mode 100644 TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/env/JSUpdateHandler.java delete mode 100644 TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/env/UIModal.java create mode 100644 TASMAN-webapp/src/main/webapp/resources/tsm_components/print_credentials.xhtml delete mode 100644 TASMAN-webapp/src/main/webapp/schemaSelection.xhtml diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TapSchema.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TapSchema.java index f3d6ade..36a4e77 100644 --- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TapSchema.java +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TapSchema.java @@ -29,7 +29,6 @@ import it.inaf.ia2.tsm.model.PropertyModel; import it.inaf.ia2.tsm.model.TableModel; import it.inaf.ia2.tsm.model.TapSchemaModel; import it.inaf.ia2.tsm.model.TapSchemaModels; -import it.inaf.ia2.tsm.model.Tasman; import java.io.Serializable; import java.sql.SQLException; import java.util.ArrayList; @@ -45,8 +44,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * The main implementation of {@link TapSchema}. - * * @author Sonia Zorba {@literal <zorba at oats.inaf.it>} */ public class TapSchema implements EntitiesContainer<Schema>, Serializable { diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/DBBroker.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/DBBroker.java index 768fcaf..0ead895 100644 --- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/DBBroker.java +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/DBBroker.java @@ -41,9 +41,9 @@ public interface DBBroker { List<String> getAllSchemaNames() throws SQLException; List<String> getAllTAPSchemaNames(List<String> allSchemas) throws SQLException; - + String detectVersion(String tapSchemaName) throws SQLException; - + List<String> getExposedSchemas(String tapSchemaName) throws SQLException; List<String> getAllTablesNames(String schemaName) throws SQLException; diff --git a/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/ConfigurationManager.java b/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/ConfigurationManager.java index 8a11d97..7e3a8f9 100644 --- a/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/ConfigurationManager.java +++ b/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/ConfigurationManager.java @@ -101,6 +101,15 @@ public class ConfigurationManager { return Collections.unmodifiableList(usersConfig.getUsers()); } + public UserConfiguration getUserConfiguration(String username) { + for (UserConfiguration user : usersConfig.getUsers()) { + if (username.equals(user.getUsername())) { + return user; + } + } + return null; + } + public List<UCDConfiguration> getUCDConfiguration() { return Collections.unmodifiableList(ucdListConfig.getUCDList()); } @@ -197,9 +206,17 @@ public class ConfigurationManager { } public List<TapCredentials> getCredentials(String username) { + List<TapCredentials> credentials = getUserCredentials(username); + if (credentials == null) { + return null; + } + return Collections.unmodifiableList(credentials); + } + + private List<TapCredentials> getUserCredentials(String username) { for (UserConfiguration user : usersConfig.getUsers()) { if (user.getUsername().equals(username)) { - return Collections.unmodifiableList(user.getCredentialsInfo()); + return user.getCredentialsInfo(); } } return null; @@ -213,18 +230,11 @@ public class ConfigurationManager { * otherwise. */ public synchronized boolean addCredentials(String username, TapCredentials credentials) { - for (UserConfiguration user : usersConfig.getUsers()) { - if (user.getUsername().equals(username)) { - for (TapCredentials tapCredentials : user.getCredentialsInfo()) { - if (tapCredentials.equals(credentials)) { - return false; - } - } - - user.getCredentialsInfo().add(credentials); - updateUsersConfigurationFile(); - return false; - } + List<TapCredentials> userCredentials = getUserCredentials(username); + if (userCredentials != null) { + userCredentials.add(credentials); + updateUsersConfigurationFile(); + return true; } return false; } @@ -234,11 +244,21 @@ public class ConfigurationManager { * otherwise. */ public synchronized boolean deleteCredentials(String username, int credentialsIndex) { - for (UserConfiguration user : usersConfig.getUsers()) { - if (user.getUsername().equals(username)) { - user.getCredentialsInfo().remove(credentialsIndex); - return true; - } + List<TapCredentials> userCredentials = getUserCredentials(username); + if (userCredentials != null && userCredentials.size() > credentialsIndex) { + userCredentials.remove(credentialsIndex); + updateUsersConfigurationFile(); + return true; + } + return false; + } + + public synchronized boolean updateCredentials(String username, TapCredentials updatedCredentials, int index) { + List<TapCredentials> userCredentials = getUserCredentials(username); + if (userCredentials != null && userCredentials.size() > index) { + userCredentials.set(index, updatedCredentials); + updateUsersConfigurationFile(); + return true; } return false; } diff --git a/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/ConsistencyChecksBean.java b/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/ConsistencyChecksBean.java index 81b1423..f44f84d 100644 --- a/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/ConsistencyChecksBean.java +++ b/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/ConsistencyChecksBean.java @@ -71,6 +71,6 @@ public class ConsistencyChecksBean implements Serializable { } public String back() { - return "schemaSelection.xhtml?faces-redirect=true"; + return "credentialsEditing.xhtml?faces-redirect=true"; } } diff --git a/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/CredentialsEditing.java b/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/CredentialsEditing.java index 5bb68a6..3ce133c 100644 --- a/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/CredentialsEditing.java +++ b/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/CredentialsEditing.java @@ -24,9 +24,7 @@ package it.inaf.ia2.tsm.webapp; import it.inaf.ia2.tsm.webapp.xmlconfig.SeparatedCredentials; import it.inaf.ia2.tsm.datalayer.Credentials; -import it.inaf.ia2.tsm.datalayer.DBWrapper; import it.inaf.ia2.tsm.model.TapSchemaModels; -import it.inaf.ia2.tsm.webapp.env.UIModal; import it.inaf.ia2.tsm.webapp.xmlconfig.JoinedCredentials; import it.inaf.ia2.tsm.webapp.xmlconfig.TapCredentials; import java.io.IOException; @@ -60,12 +58,11 @@ public class CredentialsEditing implements Serializable { private ConfigurationManager config; @Inject - private SchemaSelectionBean schemaSelectionBean; + private TapSchemaLoader tapSchemaLoader; private Integer credentialsInEditing; private Integer credentialsToRemove; - private UIModal.StatusObserver credentialsDialogStatusObserver; private boolean credentialsDialogOpened; private List<String> tapSchemaVersions; @@ -79,12 +76,6 @@ public class CredentialsEditing implements Serializable { @PostConstruct public void init() { - this.credentialsDialogStatusObserver = new UIModal.StatusObserver() { - @Override - public void statusChanged(boolean isOpen) { - credentialsDialogOpened = isOpen; - } - }; this.tapSchemaVersions = TapSchemaModels.getAvailableVersions(); } @@ -117,7 +108,8 @@ public class CredentialsEditing implements Serializable { hasObscore = credentials.isHasObscore(); } - public void addNewCredentials() { + public void addNewCredentialsInEditing() { + credentialsInEditing = null; separateCredentials = false; sourceCredentials = new Credentials(); tapSchemaCredentials = new Credentials(); @@ -126,63 +118,73 @@ public class CredentialsEditing implements Serializable { hasObscore = false; } -// public void editCredentials(Credentials credentials, int index) { -// this.sourceCredentials = credentials; -// separateCredentials = false; -// currentEditingRow = index; -// } -// -// public void editSeparateCredentials(SeparatedCredentials sc, int index) { -// this.sourceCredentials = sc.getSourceCredentials(); -// this.tapSchemaCredentials = sc.getTapSchemaCredentials(); -// currentEditingRow = index; -// separateCredentials = true; -// } - public String loginWithJoinedCredentials(JoinedCredentials credentials) { - return loginWithDBWrapper(new DBWrapper(credentials.getCredentials())); + public void loadTapSchema(TapCredentials tapCredentials) throws SQLException { + tapSchemaLoader.tryLoadingTapSchema(tapCredentials); } - public String loginWithSeparatedCredentials(Credentials sourceCredentials, Credentials tapSchemaCredentials) { - return loginWithDBWrapper(new DBWrapper(sourceCredentials, tapSchemaCredentials)); + public void openDeleteCredentialsConfirmation(int index) throws IOException { + credentialsToRemove = index; } - private String loginWithDBWrapper(DBWrapper dbWrapper) { - - try { - dbWrapper.testConnections(); - schemaSelectionBean.setDbWrapper(dbWrapper); - return "schemaSelection.xhtml?faces-redirect=true"; - } catch (SQLException e) { - LOG.error("Exception caught", e); - FacesContext.getCurrentInstance().addMessage("main", new FacesMessage("Connection error: " + e.getMessage())); - return null; + public void confirmCredentialsDeletion() { + if (credentialsToRemove != null) { + config.deleteCredentials(user.getUsername(), credentialsToRemove); } + credentialsToRemove = null; } - public void removeCredentials(int index) throws IOException { -// getSavedCredentials().remove(index); -// config.updateUsersConfigurationFile(); + public boolean validateNotNull(FacesContext ctx, String value, String componentId, String errorMessage) { + if (value == null || value.isEmpty()) { + ctx.addMessage(componentId, new FacesMessage(errorMessage)); + return false; + } + return true; } public void saveCredentialsEdited() throws IOException { -// -// // If is editing existing, remove old for creating a new one -// if (currentEditingRow < getSavedCredentials().size()) { -// getSavedCredentials().remove(currentEditingRow); -// } -// -// if (separateCredentials) { -// SeparatedCredentials sc = new SeparatedCredentials(sourceCredentials, tapSchemaCredentials); -// getSavedCredentials().add(currentEditingRow, sc); -// } else { -// getSavedCredentials().add(currentEditingRow, sourceCredentials); -// } -// -// config.updateUsersConfigurationFile(); - } - public UIModal.StatusObserver getCredentialsDialogStatus() { - return credentialsDialogStatusObserver; + /** + * We need to validate manually to avoid problem with JSF AJAX partial + * updates. + */ + FacesContext ctx = FacesContext.getCurrentInstance(); + + /** + * Single & operator used to perform all validation. + */ + boolean validationOk + = validateNotNull(ctx, sourceCredentials.getHostname(), "main:source_hostname", "Hostname is required") + & validateNotNull(ctx, sourceCredentials.getUsername(), "main:source_username", "Username is required") + & validateNotNull(ctx, tapSchemaName, "main:tap_schema_name", "TAP_SCHEMA name is required"); + + if (separateCredentials) { + validationOk = validationOk + & validateNotNull(ctx, tapSchemaCredentials.getHostname(), "main:tap_schema_hostname", "Hostname is required") + & validateNotNull(ctx, tapSchemaCredentials.getHostname(), "main:tap_schema_username", "Username is required"); + } + + if (!validationOk) { + return; + } + + TapCredentials editedCredentials; + if (separateCredentials) { + editedCredentials = new SeparatedCredentials(sourceCredentials, tapSchemaCredentials); + } else { + editedCredentials = new JoinedCredentials(sourceCredentials); + } + + editedCredentials.setHasObscore(hasObscore); + editedCredentials.setTapSchemaName(tapSchemaName); + editedCredentials.setTapSchemaVersion(tapSchemaVersion); + + if (credentialsInEditing == null) { + // New credentials + config.addCredentials(user.getUsername(), editedCredentials); + } else { + // Existing credentials + config.updateCredentials(user.getUsername(), editedCredentials, credentialsInEditing); + } } public List<String> getTapSchemaVersions() { @@ -201,33 +203,6 @@ public class CredentialsEditing implements Serializable { this.separateCredentials = separateCredentials; } -// public void separateCredentialsChanged() { -// if (separateCredentials) { -// Credentials credentials = getJoinedCredentialsInEditing().getCredentials(); -// SeparatedCredentials separatedCredentials = new SeparatedCredentials(); -// separatedCredentials.setSourceCredentials(credentials); -// credentialsInEditing = separatedCredentials; -// } else { -// Credentials credentials = getSeparatedCredentialsInEditing().getSourceCredentials(); -// JoinedCredentials joinedCredentials = new JoinedCredentials(); -// joinedCredentials.setCredentials(credentials); -// credentialsInEditing = joinedCredentials; -// } -// } -// -// public JoinedCredentials getJoinedCredentialsInEditing() { -// if (credentialsInEditing instanceof JoinedCredentials) { -// return (JoinedCredentials) credentialsInEditing; -// } -// return null; -// } -// -// public SeparatedCredentials getSeparatedCredentialsInEditing() { -// if (credentialsInEditing instanceof SeparatedCredentials) { -// return (SeparatedCredentials) credentialsInEditing; -// } -// return null; -// } public boolean isCredentialsDialogOpened() { return credentialsDialogOpened; } diff --git a/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/SchemaSelectionBean.java b/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/SchemaSelectionBean.java deleted file mode 100644 index 337614c..0000000 --- a/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/SchemaSelectionBean.java +++ /dev/null @@ -1,311 +0,0 @@ -/* - * _____________________________________________________________________________ - * - * INAF - OATS National Institute for Astrophysics - Astronomical Observatory of - * Trieste INAF - IA2 Italian Center for Astronomical Archives - * _____________________________________________________________________________ - * - * Copyright (C) 2016 Istituto Nazionale di Astrofisica - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License Version 3 as published by the - * Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 51 - * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package it.inaf.ia2.tsm.webapp; - -import it.inaf.ia2.tsm.TapSchema; -import it.inaf.ia2.tsm.datalayer.DBBroker; -import it.inaf.ia2.tsm.datalayer.DBBrokerFactory; -import it.inaf.ia2.tsm.datalayer.DBWrapper; -import it.inaf.ia2.tsm.model.TapSchemaModel; -import it.inaf.ia2.tsm.model.TapSchemaModels; -import java.io.Serializable; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import javax.annotation.PostConstruct; -import javax.faces.application.FacesMessage; -import javax.faces.component.UIComponent; -import javax.faces.context.FacesContext; -import javax.faces.validator.ValidatorException; -import javax.inject.Inject; -import javax.inject.Named; -import org.apache.deltaspike.core.api.scope.WindowScoped; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * @author Sonia Zorba {@literal <zorba at oats.inaf.it>} - */ -@Named("schemaSelection") -@WindowScoped -public class SchemaSelectionBean implements Serializable { - - private static final long serialVersionUID = -5745720427701334323L; - private static final Logger LOG = LoggerFactory.getLogger(SchemaSelectionBean.class); - - @Inject - TapSchemaEditingBean tapSchemaEditingBean; - - @Inject - ConsistencyChecksBean consistencyChecksBean; - - private DBWrapper dbWrapper; - - private String selectedRadioOption; - - // For editing - private List<String> allTAPSchemas; - private String selectedTAPSchema; - private String exposedSchemas; - - // For creation - private String tapSchemaName; - private List<String> versions; - private String version; - private List<String> allSchemas; - private List<String> selectedSchemas; - private boolean loading; - private TapSchema loadedTapSchema; - private String loadingError; - - @PostConstruct - public void init() { - selectedRadioOption = "edit"; - exposedSchemas = ""; - versions = new ArrayList<>(); - Iterator<TapSchemaModel> ite = TapSchemaModels.getIterator(); - while (ite.hasNext()) { - TapSchemaModel model = ite.next(); - versions.add(model.getVersion()); - } - Collections.sort(versions); - } - - public void onPageLoad() { - FacesContext fc = FacesContext.getCurrentInstance(); - final boolean ajaxRequest = fc.getPartialViewContext().isAjaxRequest(); - final boolean validationFailed = fc.isValidationFailed(); - - if (!ajaxRequest && !validationFailed) { - - // Loading all schemas of the source database - try { - DBBroker broker = DBBrokerFactory.getDBBroker(dbWrapper.getSourceDataSourceWrapper()); - allSchemas = broker.getAllSchemaNames(); - setSelectedSchemas(new ArrayList<String>()); - } catch (SQLException e) { - throw new RuntimeException(e); - } - - // Loading all schemas of the TAP_SCHEMA database - try { - DBBroker broker = DBBrokerFactory.getDBBroker(dbWrapper.getTapSchemaDataSourceWrapper()); - allTAPSchemas = broker.getAllTAPSchemaNames(allSchemas); - - if (!allTAPSchemas.isEmpty()) { - this.selectedTAPSchema = allTAPSchemas.get(0); - loadExposedSchemas(); - } - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - } - - private void loadExposedSchemas() throws SQLException { - DBBroker broker = DBBrokerFactory.getDBBroker(dbWrapper.getTapSchemaDataSourceWrapper()); - List<String> schemas = broker.getExposedSchemas(selectedTAPSchema); - exposedSchemas = ""; - for (int i = 0; i < schemas.size(); i++) { - exposedSchemas += schemas.get(i); - if (i < schemas.size() - 1) { - exposedSchemas += ", "; - } - } - } - - public List<String> getAllTAPSchemas() { - return allTAPSchemas; - } - - public List<String> getAllSchemas() { - return allSchemas; - } - - public String getExposedSchemas() { - return exposedSchemas; - } - - public String getSelectedRadioOption() { - return selectedRadioOption; - } - - public void setSelectedRadioOption(String selectedRadioOption) { - this.selectedRadioOption = selectedRadioOption; - } - - public String getSelectedTAPSchema() { - return selectedTAPSchema; - } - - public void setSelectedTAPSchema(String selectedTAPSchema) { - this.selectedTAPSchema = selectedTAPSchema; - } - - public void selectedTAPSchemaChanged() { - try { - loadExposedSchemas(); - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - - public List<String> getSelectedSchemas() { - return selectedSchemas; - } - - public void setSelectedSchemas(List<String> selectedSchemas) { - this.selectedSchemas = selectedSchemas; - } - - public String openLoaded() { - if (loadedTapSchema.getConsistencyChecks().isInconsistent()) { - consistencyChecksBean.setDbWrapper(dbWrapper); - consistencyChecksBean.setTapSchema(loadedTapSchema); - return "consistencyChecks.xhtml?faces-redirect=true"; - } else { - tapSchemaEditingBean.setTapSchema(loadedTapSchema); - return "tapSchemaEditing.xhtml?faces-redirect=true"; - } - } - - public void edit() { - - loadedTapSchema = null; - loading = true; - loadingError = null; - - new Thread(new Runnable() { - @Override - public void run() { - try { - DBBroker broker = DBBrokerFactory.getDBBroker(dbWrapper.getTapSchemaDataSourceWrapper()); - String version = broker.detectVersion(selectedTAPSchema); - loadedTapSchema = new TapSchema(version, dbWrapper, selectedTAPSchema, true); - } catch (Throwable e) { - LOG.error("Exception caught", e); - loadingError = e.getMessage(); - if (loadingError == null) { - loadingError = e.getClass().getCanonicalName(); - } - } - loading = false; - } - }).start(); - } - - public void create() { - - loadedTapSchema = null; - loading = true; - loadingError = null; - - new Thread(new Runnable() { - @Override - public void run() { - try { - loadedTapSchema = new TapSchema(version, dbWrapper, tapSchemaName, false); - for (String schemaName : selectedSchemas) { - loadedTapSchema.addChild(schemaName); - } - } catch (Throwable e) { - LOG.error("Exception caught", e); - if (e.getMessage() != null) { - loadingError = e.getMessage(); - } else { - loadingError = e.getClass().getCanonicalName(); - loadedTapSchema = null; - } - } - loading = false; - } - }).start(); - } - - public String getTapSchemaName() { - return tapSchemaName; - } - - public void setTapSchemaName(String tapSchemaName) { - this.tapSchemaName = tapSchemaName; - } - - public DBWrapper getDbWrapper() { - return dbWrapper; - } - - public void setDbWrapper(DBWrapper dbWrapper) { - this.dbWrapper = dbWrapper; - } - - public void validateTapSchemaName(FacesContext context, UIComponent inputComponent, Object value) { - String textValue = (String) value; - - String validatorMessage = null; - if (textValue == null || textValue.isEmpty()) { - validatorMessage = "TAP_SCHEMA name is required"; - } else if (!textValue.matches("^[a-zA-Z0-9_[-]]*$")) { - validatorMessage = "TAP_SCHEMA name has to be a valid table name"; - } else if (allSchemas.contains(textValue)) { - validatorMessage = "Database already contains a schema with this name. Please choose another name"; - } - - if (validatorMessage != null) { - throw new ValidatorException(new FacesMessage(validatorMessage)); - } - } - - /** - * This boolean is true when a TapSchema instance is loading. - */ - public boolean isLoading() { - return loading; - } - - /** - * This String is not null when an error happens while a TapSchema is - * loading. - */ - public String getLoadingError() { - return loadingError; - } - - public TapSchema getLoadedTapSchema() { - return loadedTapSchema; - } - - public List<String> getVersions() { - return versions; - } - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } -} diff --git a/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/TapSchemaEditingBean.java b/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/TapSchemaEditingBean.java index c5f3612..bedc26f 100644 --- a/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/TapSchemaEditingBean.java +++ b/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/TapSchemaEditingBean.java @@ -25,7 +25,6 @@ package it.inaf.ia2.tsm.webapp; import it.inaf.ia2.tsm.ChildEntity; import it.inaf.ia2.tsm.Column; import it.inaf.ia2.tsm.webapp.env.CustomPartialResponseWriter; -import it.inaf.ia2.tsm.webapp.env.JSUpdateHandler; import it.inaf.ia2.tsm.EntitiesContainer; import it.inaf.ia2.tsm.Key; import it.inaf.ia2.tsm.KeyColumn; @@ -58,7 +57,7 @@ public class TapSchemaEditingBean implements Serializable { private static final Logger LOG = LoggerFactory.getLogger(TapSchemaEditingBean.class); @Inject - SchemaSelectionBean schemaSelection; + private TapSchemaLoader tapSchemaLoader; private TapSchema tapSchema; private Schema selectedSchema; @@ -247,7 +246,7 @@ public class TapSchemaEditingBean implements Serializable { } public String back() { - return "schemaSelection.xhtml?faces-redirect=true"; + return "credentialsEditing.xhtml?faces-redirect=true"; } public void undoRemove(ChildEntity entity) throws SQLException { @@ -310,13 +309,7 @@ public class TapSchemaEditingBean implements Serializable { } // New UCD is set and we can notify the client to close the UCD Search modal dialog. - CustomPartialResponseWriter.getCurrentInstance().addCustomJSUpdate(new JSUpdateHandler() { - - @Override - public String getUpdate() { - return "true"; - } - }); + CustomPartialResponseWriter.getCurrentInstance().addCustomJSUpdate(String.valueOf(true)); } } @@ -338,13 +331,7 @@ public class TapSchemaEditingBean implements Serializable { if (key.equals("unit")) { voUnitValidator = new VOUnitValidator(entity.getValue(key, String.class)); } - CustomPartialResponseWriter.getCurrentInstance().addCustomJSUpdate(new JSUpdateHandler() { - - @Override - public String getUpdate() { - return isChanged + ""; - } - }); + CustomPartialResponseWriter.getCurrentInstance().addCustomJSUpdate(String.valueOf(isChanged)); } public void removeColumn(String name) { @@ -371,17 +358,10 @@ public class TapSchemaEditingBean implements Serializable { public void reload() { - if (schemaSelection.getSelectedRadioOption().equals("edit")) { - schemaSelection.edit(); + if (tapSchema.exists()) { + tapSchemaLoader.edit(); } else { - if (tapSchema.exists()) { - schemaSelection.setSelectedRadioOption("edit"); - schemaSelection.setSelectedTAPSchema(tapSchema.getName()); - schemaSelection.selectedTAPSchemaChanged(); - schemaSelection.edit(); - } else { - schemaSelection.create(); - } + tapSchemaLoader.create(); } } diff --git a/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/TapSchemaLoader.java b/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/TapSchemaLoader.java new file mode 100644 index 0000000..ff5951b --- /dev/null +++ b/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/TapSchemaLoader.java @@ -0,0 +1,172 @@ +/* + * _____________________________________________________________________________ + * + * INAF - OATS National Institute for Astrophysics - Astronomical Observatory of + * Trieste INAF - IA2 Italian Center for Astronomical Archives + * _____________________________________________________________________________ + * + * Copyright (C) 2017 Istituto Nazionale di Astrofisica + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License Version 3 as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package it.inaf.ia2.tsm.webapp; + +import it.inaf.ia2.tsm.TapSchema; +import it.inaf.ia2.tsm.datalayer.DBBroker; +import it.inaf.ia2.tsm.datalayer.DBBrokerFactory; +import it.inaf.ia2.tsm.datalayer.DBWrapper; +import it.inaf.ia2.tsm.webapp.env.CustomPartialResponseWriter; +import it.inaf.ia2.tsm.webapp.xmlconfig.JoinedCredentials; +import it.inaf.ia2.tsm.webapp.xmlconfig.SeparatedCredentials; +import it.inaf.ia2.tsm.webapp.xmlconfig.TapCredentials; +import java.io.Serializable; +import java.sql.SQLException; +import javax.inject.Inject; +import javax.inject.Named; +import org.apache.deltaspike.core.api.scope.WindowScoped; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * + * @author Sonia Zorba {@literal <zorba at oats.inaf.it>} + */ +@Named("tapSchemaLoader") +@WindowScoped +public class TapSchemaLoader implements Serializable { + + private static final long serialVersionUID = 3203810003976020854L; + + private static final Logger LOG = LoggerFactory.getLogger(TapSchemaLoader.class); + + @Inject + private ConsistencyChecksBean consistencyChecksBean; + + @Inject + TapSchemaEditingBean tapSchemaEditingBean; + + private TapCredentials tapCredentials; + private DBWrapper dbWrapper; + + private boolean loading; + private TapSchema loadedTapSchema; + private String loadingError; + + public void tryLoadingTapSchema(TapCredentials tapCredentials) throws SQLException { + this.tapCredentials = tapCredentials; + + if (tapCredentials instanceof JoinedCredentials) { + JoinedCredentials joinedCredentials = (JoinedCredentials) tapCredentials; + dbWrapper = new DBWrapper(joinedCredentials.getCredentials()); + } else { + SeparatedCredentials separatedCredentials = (SeparatedCredentials) tapCredentials; + dbWrapper = new DBWrapper(separatedCredentials.getSourceCredentials(), separatedCredentials.getTapSchemaCredentials()); + } + + // Testing connections + dbWrapper.testConnections(); + + // Searching for TAP_SCHEMA name + DBBroker broker = DBBrokerFactory.getDBBroker(dbWrapper.getTapSchemaDataSourceWrapper()); + boolean tapSchemaExists = false; + for (String schemaName : broker.getAllSchemaNames()) { + if (schemaName.equals(tapCredentials.getTapSchemaName())) { + tapSchemaExists = true; + break; + } + } + + CustomPartialResponseWriter.getCurrentInstance().addCustomJSUpdate("tap_schema_existence", String.valueOf(tapSchemaExists)); + + if (tapSchemaExists) { + edit(); + } + // Otherwise create TAP_SCHEMA only if user press Ok on confirmation dialog + } + + public void edit() { + + loadedTapSchema = null; + loading = true; + loadingError = null; + + new Thread(new Runnable() { + @Override + public void run() { + try { + loadedTapSchema = new TapSchema(tapCredentials.getTapSchemaVersion(), dbWrapper, tapCredentials.getTapSchemaName(), true); + } catch (Throwable e) { + LOG.error("Exception caught", e); + loadingError = e.getMessage(); + if (loadingError == null) { + loadingError = e.getClass().getCanonicalName(); + } + } + loading = false; + } + }).start(); + } + + public void create() { + + loadedTapSchema = null; + loading = true; + loadingError = null; + + new Thread(new Runnable() { + @Override + public void run() { + try { + loadedTapSchema = new TapSchema(tapCredentials.getTapSchemaVersion(), dbWrapper, tapCredentials.getTapSchemaName(), false); + } catch (Throwable e) { + LOG.error("Exception caught", e); + if (e.getMessage() != null) { + loadingError = e.getMessage(); + } else { + loadingError = e.getClass().getCanonicalName(); + loadedTapSchema = null; + } + } + loading = false; + } + }).start(); + } + + public TapCredentials getTapCredentials() { + return tapCredentials; + } + + public boolean isLoading() { + return loading; + } + + public TapSchema getLoadedTapSchema() { + return loadedTapSchema; + } + + public String getLoadingError() { + return loadingError; + } + + public String openLoaded() { + if (loadedTapSchema.getConsistencyChecks().isInconsistent()) { + consistencyChecksBean.setDbWrapper(dbWrapper); + consistencyChecksBean.setTapSchema(loadedTapSchema); + return "consistencyChecks.xhtml?faces-redirect=true"; + } else { + tapSchemaEditingBean.setTapSchema(loadedTapSchema); + return "tapSchemaEditing.xhtml?faces-redirect=true"; + } + } +} diff --git a/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/TapSchemaLoaderResource.java b/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/TapSchemaLoaderResource.java index 7a7b0c9..77bd7c7 100644 --- a/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/TapSchemaLoaderResource.java +++ b/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/TapSchemaLoaderResource.java @@ -39,15 +39,15 @@ import javax.json.JsonObjectBuilder; public class TapSchemaLoaderResource { @Inject - private SchemaSelectionBean schemaSelection; + private TapSchemaLoader loader; @GET @Path("status") public String getStatus() { JsonObjectBuilder job = Json.createObjectBuilder(); - job.add("loading", schemaSelection.isLoading()); - if (schemaSelection.getLoadingError() != null) { - job.add("error", schemaSelection.getLoadingError()); + job.add("loading", loader.isLoading()); + if (loader.getLoadingError() != null) { + job.add("error", loader.getLoadingError()); } return job.build().toString(); } diff --git a/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/UsersEditing.java b/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/UsersEditing.java index e2e9053..9a578e8 100644 --- a/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/UsersEditing.java +++ b/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/UsersEditing.java @@ -23,7 +23,6 @@ package it.inaf.ia2.tsm.webapp; import it.inaf.ia2.tsm.webapp.env.CustomPartialResponseWriter; -import it.inaf.ia2.tsm.webapp.env.JSUpdateHandler; import it.inaf.ia2.tsm.webapp.xmlconfig.UserConfiguration; import java.io.Serializable; import java.util.List; @@ -142,13 +141,7 @@ public class UsersEditing implements Serializable { canSave = false; } - final String jsUpdate = String.valueOf(canSave); - CustomPartialResponseWriter.getCurrentInstance().addCustomJSUpdate(new JSUpdateHandler() { - @Override - public String getUpdate() { - return jsUpdate; - } - }); + CustomPartialResponseWriter.getCurrentInstance().addCustomJSUpdate(String.valueOf(canSave)); if (canSave) { if (newUser) { diff --git a/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/env/CustomPartialResponseWriter.java b/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/env/CustomPartialResponseWriter.java index 431d503..9164274 100644 --- a/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/env/CustomPartialResponseWriter.java +++ b/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/env/CustomPartialResponseWriter.java @@ -36,7 +36,7 @@ import javax.faces.context.ResponseWriter; */ public class CustomPartialResponseWriter extends PartialResponseWriter { - private final Map<String, JSUpdateHandler> customJSUpdates; + private final Map<String, String> customJSUpdates; public CustomPartialResponseWriter(ResponseWriter wrapped) { super(wrapped); @@ -47,11 +47,11 @@ public class CustomPartialResponseWriter extends PartialResponseWriter { public void endDocument() throws IOException { if (!customJSUpdates.isEmpty()) { startExtension(Collections.singletonMap("id", "jsupdates")); - for (Map.Entry<String, JSUpdateHandler> entry : customJSUpdates.entrySet()) { + for (Map.Entry<String, String> entry : customJSUpdates.entrySet()) { String componentId = entry.getKey(); startElement("jsupdate", null); writeAttribute("src", componentId, null); - write(entry.getValue().getUpdate()); + write(entry.getValue()); endElement("jsupdate"); } endExtension(); @@ -60,13 +60,13 @@ public class CustomPartialResponseWriter extends PartialResponseWriter { super.endDocument(); } - public void addCustomJSUpdate(String componentId, JSUpdateHandler updateHandler) { - customJSUpdates.put(componentId, updateHandler); + public void addCustomJSUpdate(String key, String jsUpdate) { + customJSUpdates.put(key, jsUpdate); } - public void addCustomJSUpdate(JSUpdateHandler updateHandler) { + public void addCustomJSUpdate(String jsUpdate) { String sourceComponentId = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("javax.faces.source"); - addCustomJSUpdate(sourceComponentId, updateHandler); + addCustomJSUpdate(sourceComponentId, jsUpdate); } public static CustomPartialResponseWriter getCurrentInstance() { diff --git a/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/env/JSUpdateHandler.java b/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/env/JSUpdateHandler.java deleted file mode 100644 index dc63045..0000000 --- a/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/env/JSUpdateHandler.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * _____________________________________________________________________________ - * - * INAF - OATS National Institute for Astrophysics - Astronomical Observatory of - * Trieste INAF - IA2 Italian Center for Astronomical Archives - * _____________________________________________________________________________ - * - * Copyright (C) 2016 Istituto Nazionale di Astrofisica - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License Version 3 as published by the - * Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 51 - * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package it.inaf.ia2.tsm.webapp.env; - -/** - * - * @author Sonia Zorba {@literal <zorba at oats.inaf.it>} - */ -public abstract class JSUpdateHandler { - - public abstract String getUpdate(); -} diff --git a/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/env/UIModal.java b/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/env/UIModal.java deleted file mode 100644 index 5444db3..0000000 --- a/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/env/UIModal.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * _____________________________________________________________________________ - * - * INAF - OATS National Institute for Astrophysics - Astronomical Observatory of - * Trieste INAF - IA2 Italian Center for Astronomical Archives - * _____________________________________________________________________________ - * - * Copyright (C) 2017 Istituto Nazionale di Astrofisica - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License Version 3 as published by the - * Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 51 - * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package it.inaf.ia2.tsm.webapp.env; - -import java.io.IOException; -import javax.faces.component.FacesComponent; -import javax.faces.component.UIComponentBase; -import javax.faces.context.FacesContext; -import javax.faces.context.ResponseWriter; - -/** - * - * @author Sonia Zorba {@literal <zorba at oats.inaf.it>} - */ -@FacesComponent(tagName = "modal", namespace = "http://ia2.inaf.it/component", createTag = true) -public class UIModal extends UIComponentBase { - - public static abstract class StatusObserver { - - public abstract void statusChanged(boolean isOpen); - } - - @Override - public void decode(FacesContext context) { - - if (getAttributes().containsKey("status-observer")) { - StatusObserver status = (StatusObserver) getAttributes().get("status-observer"); - boolean open = Boolean.parseBoolean((String) getAttributes().get("open")); - status.statusChanged(open); - } - } - - @Override - public String getFamily() { - return "modal"; - } - - @Override - public void encodeBegin(FacesContext context) throws IOException { - ResponseWriter writer = context.getResponseWriter(); - writer.write("<div class=\"modal fade\" tabindex=\"-1\" role=\"dialog\" id=\""); - writer.write(getClientId()); - writer.write("\">"); - } - - @Override - public void encodeEnd(FacesContext context) throws IOException { - ResponseWriter writer = context.getResponseWriter(); - writer.write("</div>"); - } -} diff --git a/TASMAN-webapp/src/main/webapp/credentialsEditing.xhtml b/TASMAN-webapp/src/main/webapp/credentialsEditing.xhtml index fe29f2c..ab1f7da 100644 --- a/TASMAN-webapp/src/main/webapp/credentialsEditing.xhtml +++ b/TASMAN-webapp/src/main/webapp/credentialsEditing.xhtml @@ -10,6 +10,8 @@ <ui:define name="scripts"> <h:outputScript library="js" name="credentials.js"></h:outputScript> <h:outputScript library="js" name="ucd-editor.js"></h:outputScript> + <h:outputScript library="js" name="async-loader.js"></h:outputScript> + <script>TSM.asyncLoader.init(#{tapSchemaLoader.loading});</script> </ui:define> <ui:define name="content"> <f:event listener="#{loggedInChecker.checkFromNonIndex()}" type="preRenderView" /> @@ -26,57 +28,62 @@ </div> <h:panelGroup id="saved-credentials"> - <ui:repeat value="#{credentialsInsertion.savedCredentials}" var="c" varStatus="loop"> - <div class="panel panel-default"> - <div class="panel-body"> - <h:panelGroup rendered="#{c.class.simpleName eq 'Credentials'}"> - <div class="col-xs-10"> - <h:commandLink action="#{credentialsInsertion.removeCredentials(loop.index)}" title="Delete"> - <span class="glyphicon glyphicon-trash"></span> - <f:ajax execute="@this" render="@form" /> - </h:commandLink> - <h:commandLink action="#{credentialsInsertion.editCredentials(c, loop.index)}" title="Edit"> - <span class="glyphicon glyphicon-pencil"></span> - <f:ajax execute="@this" render=":main:credentials-modal-body" onevent="credentials.editClicked" /> - </h:commandLink> - (${c.databaseType eq 'MYSQL' ? 'MySQL' : 'Postgres'}) ${c.hostname}:${c.port} ${c.username} - </div> - <div class="col-xs-2 text-right"> - <h:commandLink action="#{credentialsInsertion.loginWithJoinedCredentials(c)}" title="Login" immediate="true"> - <span class="glyphicon glyphicon-log-in"></span> - </h:commandLink> - </div> - </h:panelGroup> - <h:panelGroup rendered="#{c.class.simpleName eq 'SeparateCredentials'}"> - <div class="col-xs-10"> - <h:commandLink action="#{credentialsInsertion.removeCredentials(loop.index)}" title="Delete"> - <span class="glyphicon glyphicon-trash"></span> - <f:ajax execute="@this" render="@form" /> - </h:commandLink> - <h:commandLink action="#{credentialsInsertion.editSeparateCredentials(c, loop.index)}" title="Edit"> - <span class="glyphicon glyphicon-pencil"></span> - <f:ajax execute="@this" render=":main:credentials-modal-body" onevent="credentials.editClicked" /> - </h:commandLink> - <strong>Source</strong> - (${c.sourceCredentials.databaseType eq 'MYSQL' ? 'MySQL' : 'Postgres'}) ${c.sourceCredentials.hostname}:${c.sourceCredentials.port} ${c.sourceCredentials.username} - <strong>TAP_SCHEMA</strong> - (${c.tapSchemaCredentials.databaseType eq 'MYSQL' ? 'MySQL' : 'Postgres'}) ${c.tapSchemaCredentials.hostname}:${c.tapSchemaCredentials.port} ${c.tapSchemaCredentials.username} - </div> - <div class="col-xs-2 text-right"> - <h:commandLink action="#{credentialsInsertion.loginWithSeparatedCredentials(c.sourceCredentials, c.tapSchemaCredentials)}" title="Login" immediate="true"> - <span class="glyphicon glyphicon-log-in"></span> - </h:commandLink> - </div> - </h:panelGroup> - </div> - </div> - </ui:repeat> + + <h:panelGroup rendered="#{credentialsInsertion.savedCredentials.size() gt 0}"> + <table class="table table-striped"> + <thead> + <tr> + <th></th> + <th>Credentials</th> + <th>TAP_SCHEMA name</th> + <th>Version</th> + <th>Obscore</th> + <th>Login</th> + </tr> + </thead> + <tbody> + <ui:repeat value="#{credentialsInsertion.savedCredentials}" var="c" varStatus="loop"> + <tr> + <td> + <h:commandLink action="#{credentialsInsertion.openDeleteCredentialsConfirmation(loop.index)}" title="Delete" class="text-danger"> + <span class="glyphicon glyphicon-trash"></span> + <f:ajax execute="@this" render="@form" onevent="credentials.openConfirmDeleteModal" /> + </h:commandLink> + <h:commandLink action="#{credentialsInsertion.editCredentials(loop.index)}" title="Edit"> + <span class="glyphicon glyphicon-pencil"></span> + <f:ajax execute="@this" render=":main:credentials-modal-body" onevent="credentials.editClicked" /> + </h:commandLink> + </td> + <td> + <h:panelGroup rendered="#{c.class.simpleName eq 'JoinedCredentials'}"> + <tsm_components:print_credentials credentials="#{c.credentials}" /> + </h:panelGroup> + <h:panelGroup rendered="#{c.class.simpleName eq 'SeparatedCredentials'}"> + <tsm_components:print_credentials credentials="#{c.sourceCredentials}" /> + <span class="glyphicon glyphicon-arrow-right"></span> + <tsm_components:print_credentials credentials="#{c.tapSchemaCredentials}" /> + </h:panelGroup> + </td> + <td>#{c.tapSchemaName}</td> + <td>#{c.tapSchemaVersion}</td> + <td><span class="glyphicon glyphicon-#{c.hasObscore ? 'ok':'remove'}"></span></td> + <td> + <h:commandLink action="#{credentialsInsertion.loadTapSchema(c)}" title="Login" immediate="true"> + <span class="glyphicon glyphicon-log-in"></span> + <f:ajax execute="@form" render="@form" onevent="TSM.asyncLoader.openTapSchemaClicked" /> + </h:commandLink> + </td> + </tr> + </ui:repeat> + </tbody> + </table> + </h:panelGroup> <p class="text-danger text-center"><strong><h:message for="main" /></strong></p> <div class="text-center"> <br/><br/> - <h:commandLink class="btn btn-success" action="#{credentialsInsertion.addNewCredentials()}"> + <h:commandLink class="btn btn-success" action="#{credentialsInsertion.addNewCredentialsInEditing()}"> <span class="glyphicon glyphicon-plus"></span> Add new database credentials <f:ajax execute="@this" render="credentials-modal-body" onevent="credentials.editClicked" /> @@ -84,7 +91,7 @@ </div> </h:panelGroup> - <ia2:modal id="credentials-modal" visibility-status="#{credentialsInsertion.credentialsDialogStatus}"> + <div class="modal fade" tabindex="-1" role="dialog" id="credentials-modal"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> @@ -100,7 +107,7 @@ <h3 class="panel-title">Source credentials</h3> </div> <div class="panel-body"> - <h:panelGroup layout="block" class="form-horizontal" id="source_credentials"> + <h:panelGroup layout="block" class="form-horizontal" id="source_credentials" rendered="#{credentialsInsertion.sourceCredentials ne null}"> <div class="form-group"> <h:outputLabel for="source_dbtype" class="#{credentialsInsertion.separateCredentials ? 'col-xs-4': 'col-xs-3'} control-label">Database type</h:outputLabel> <div class="#{credentialsInsertion.separateCredentials ? 'col-xs-8': 'col-xs-9'}"> @@ -114,21 +121,21 @@ <div class="form-group"> <h:outputLabel for="source_hostname" class="#{credentialsInsertion.separateCredentials ? 'col-xs-4': 'col-xs-3'} control-label">Hostname</h:outputLabel> <div class="#{credentialsInsertion.separateCredentials ? 'col-xs-8': 'col-xs-9'}"> - <h:inputText id="source_hostname" value="#{credentialsInsertion.sourceCredentials.hostname}" class="form-control" required="#{credentialsInsertion.credentialsDialogOpened}" requiredMessage="Hostname is required"/> + <h:inputText id="source_hostname" value="#{credentialsInsertion.sourceCredentials.hostname}" class="form-control" /> <h:message for="source_hostname" class="text-danger" /> </div> </div> <div class="form-group"> <h:outputLabel for="source_port" class="#{credentialsInsertion.separateCredentials ? 'col-xs-4': 'col-xs-3'} control-label">Port</h:outputLabel> <div class="#{credentialsInsertion.separateCredentials ? 'col-xs-8': 'col-xs-9'}"> - <h:inputText id="source_port" value="#{credentialsInsertion.sourceCredentials.port}" class="form-control" required="#{credentialsInsertion.credentialsDialogOpened}" requiredMessage="Port is required"/> + <h:inputText id="source_port" value="#{credentialsInsertion.sourceCredentials.port}" class="form-control" /> <h:message for="source_port" class="text-danger" /> </div> </div> <div class="form-group"> <h:outputLabel for="source_username" class="#{credentialsInsertion.separateCredentials ? 'col-xs-4': 'col-xs-3'} control-label">Username</h:outputLabel> <div class="#{credentialsInsertion.separateCredentials ? 'col-xs-8': 'col-xs-9'}"> - <h:inputText id="source_username" value="#{credentialsInsertion.sourceCredentials.username}" required="#{credentialsInsertion.credentialsDialogOpened}" class="form-control" requiredMessage="Username is required"/> + <h:inputText id="source_username" value="#{credentialsInsertion.sourceCredentials.username}" class="form-control" /> <h:message for="source_username" class="text-danger" /> </div> </div> @@ -151,7 +158,7 @@ </div> </div> <div class="#{credentialsInsertion.separateCredentials ? 'col-xs-6':'col-xs-12'}"> - <h:panelGroup layout="block" class="panel panel-primary" rendered="#{credentialsInsertion.separateCredentials}"> + <h:panelGroup layout="block" class="panel panel-primary" rendered="#{credentialsInsertion.separateCredentials and credentialsInsertion.tapSchemaCredentials ne null}"> <h:panelGroup layout="block" class="panel-heading" rendered="#{credentialsInsertion.separateCredentials}"> <h3 class="panel-title">TAP_SCHEMA credentials</h3> </h:panelGroup> @@ -170,21 +177,21 @@ <div class="form-group"> <h:outputLabel for="tap_schema_hostname" class="#{credentialsInsertion.separateCredentials ? 'col-xs-4': 'col-xs-3'} control-label">Hostname</h:outputLabel> <div class="#{credentialsInsertion.separateCredentials ? 'col-xs-8': 'col-xs-9'}"> - <h:inputText id="tap_schema_hostname" value="#{credentialsInsertion.tapSchemaCredentials.hostname}" required="#{credentialsInsertion.credentialsDialogOpened}" class="form-control" requiredMessage="Hostname is required"/> + <h:inputText id="tap_schema_hostname" value="#{credentialsInsertion.tapSchemaCredentials.hostname}" class="form-control" /> <h:message for="tap_schema_hostname" class="text-danger" /> </div> </div> <div class="form-group"> <h:outputLabel for="tap_schema_port" class="#{credentialsInsertion.separateCredentials ? 'col-xs-4': 'col-xs-3'} control-label">Port</h:outputLabel> <div class="#{credentialsInsertion.separateCredentials ? 'col-xs-8': 'col-xs-9'}"> - <h:inputText id="tap_schema_port" value="#{credentialsInsertion.tapSchemaCredentials.port}" required="#{credentialsInsertion.credentialsDialogOpened}" class="form-control" requiredMessage="Port is required"/> + <h:inputText id="tap_schema_port" value="#{credentialsInsertion.tapSchemaCredentials.port}" class="form-control" /> <h:message for="tap_schema_port" class="text-danger" /> </div> </div> <div class="form-group"> <h:outputLabel for="tap_schema_username" class="#{credentialsInsertion.separateCredentials ? 'col-xs-4': 'col-xs-3'} control-label">Username</h:outputLabel> <div class="#{credentialsInsertion.separateCredentials ? 'col-xs-8': 'col-xs-9'}"> - <h:inputText id="tap_schema_username" value="#{credentialsInsertion.tapSchemaCredentials.username}" required="#{credentialsInsertion.credentialsDialogOpened}" class="form-control" requiredMessage="Username is required"/> + <h:inputText id="tap_schema_username" value="#{credentialsInsertion.tapSchemaCredentials.username}" class="form-control" /> <h:message for="tap_schema_username" class="text-danger" /> </div> </div> @@ -212,7 +219,7 @@ <div class="form-group"> <label class="col-xs-6 col-xs-offset-4"> <h:selectBooleanCheckbox value="#{credentialsInsertion.separateCredentials}" id="separate-credentials"> - <f:ajax render="credentials_panels_wrapper" execute="@this" onevent="credentials.separateCredentialsChanged" /> + <f:ajax render="credentials_panels_wrapper" execute="@form" onevent="credentials.separateCredentialsChanged" /> </h:selectBooleanCheckbox> Separate credentials </label> @@ -220,14 +227,15 @@ <div class="form-group"> <h:outputLabel for="tap_schema_name" class="control-label col-xs-4">TAP_SCHEMA name</h:outputLabel> <div class="col-xs-6"> - <h:inputText value="#{credentialsInsertion.tapSchemaName}" class="form-control" /> + <h:inputText value="#{credentialsInsertion.tapSchemaName}" id="tap_schema_name" class="form-control" /> + <h:message for="tap_schema_name" class="text-danger" /> </div> </div> <div class="form-group"> - <h:outputLabel for="tap_schema_name" class="control-label col-xs-4">TAP_SCHEMA version</h:outputLabel> + <h:outputLabel for="tap_schema_version" class="control-label col-xs-4">TAP_SCHEMA version</h:outputLabel> <div class="col-xs-6"> <h:selectOneMenu value="#{credentialsInsertion.tapSchemaVersion}" class="form-control"> - <f:selectItems value="#{credentialsInsertion.tapSchemaVersions}" var="version" itemLabel="#{version}" itemDescription="#{version}" /> + <f:selectItems value="#{credentialsInsertion.tapSchemaVersions}" var="version" itemLabel="#{version}" itemDescription="#{version}" id="tap_schema_version" /> </h:selectOneMenu> </div> </div> @@ -248,10 +256,53 @@ </div> </div> </div> - </ia2:modal> + </div> + + <div class="modal fade" tabindex="-1" role="dialog" id="modal-confirm-credentials-deletion"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> + <h4 class="modal-title">Confirm deletion</h4> + </div> + <div class="modal-body"> + <p>Do you really want to delete this credentials?</p> + </div> + <div class="modal-footer"> + <h:commandButton class="btn btn-danger" value="Confirm" action="#{credentialsInsertion.confirmCredentialsDeletion()}"> + <f:ajax execute="@form" render=":main:saved-credentials" onevent="credentials.closeConfirmDeleteModal" /> + </h:commandButton> + </div> + </div> + </div> + </div> <tsm_components:ucd_editor id="ucd-editor" /> </div> + + <div class="modal fade" tabindex="-1" role="dialog" id="modal-confirm-ts-creation"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> + <h4 class="modal-title">Create TAP_SCHEMA</h4> + </div> + <div class="modal-body"> + The TAP_SCHEMA <strong>#{tapSchemaLoader.tapCredentials.tapSchemaName}</strong> doesn't exists. Do you want to create it? + </div> + <div class="modal-footer"> + <h:commandButton class="btn btn-success" value="Yes" action="#{tapSchemaLoader.create()}"> + <f:ajax execute="@this" render="@none" onevent="TSM.asyncLoader.tapSchemaCreationConfirmed" /> + </h:commandButton> + <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button> + </div> + </div> + </div> + </div> + </h:form> + + <h:form id="async-loader" class="hide"> + <h:commandButton action="#{tapSchemaLoader.openLoaded()}" id="open-loaded" /> </h:form> </ui:define> </ui:composition> diff --git a/TASMAN-webapp/src/main/webapp/resources/js/async-loader.js b/TASMAN-webapp/src/main/webapp/resources/js/async-loader.js index 0f2e31d..d3eda57 100644 --- a/TASMAN-webapp/src/main/webapp/resources/js/async-loader.js +++ b/TASMAN-webapp/src/main/webapp/resources/js/async-loader.js @@ -27,8 +27,20 @@ init: function (l) { loading = l; }, - startChecking: function (event) { + openTapSchemaClicked: function (event) { if (event.status === 'success' && $('.validation-message').length === 0) { + var $tsExistenceEl = $(event.responseXML).find('jsupdate[src="tap_schema_existence"]'); + if ($tsExistenceEl.length === 1) { + if ($tsExistenceEl.text() === 'true') { + periodicCheck(); + } else { + $('#modal-confirm-ts-creation').modal('show'); + } + } + } + }, + tapSchemaCreationConfirmed: function (event) { + if (event.status === 'success') { periodicCheck(); } } diff --git a/TASMAN-webapp/src/main/webapp/resources/js/common.js b/TASMAN-webapp/src/main/webapp/resources/js/common.js index c525d2d..1ca96ad 100644 --- a/TASMAN-webapp/src/main/webapp/resources/js/common.js +++ b/TASMAN-webapp/src/main/webapp/resources/js/common.js @@ -89,7 +89,8 @@ // Setup loading animation jsf.ajax.addOnEvent(function (data) { - if ($(data.source).is('input[type="text"]')) { + if ($(data.source).is('input[type="text"]') || + $(data.source).is('[data-jsf-modal]')) { return; // special case } switch (data.status) { diff --git a/TASMAN-webapp/src/main/webapp/resources/js/credentials.js b/TASMAN-webapp/src/main/webapp/resources/js/credentials.js index 5fb483c..bd8ce12 100644 --- a/TASMAN-webapp/src/main/webapp/resources/js/credentials.js +++ b/TASMAN-webapp/src/main/webapp/resources/js/credentials.js @@ -2,19 +2,19 @@ function checkSeparateCredentials() { var separateCredentials = $('#main\\:separate-credentials').is(':checked'); - $('#main\\:credentials-modal .modal-dialog').toggleClass('modal-lg', separateCredentials); + $('#credentials-modal .modal-dialog').toggleClass('modal-lg', separateCredentials); } window.credentials = { editClicked: function (event) { if (event.status === 'success') { - $('#main\\:credentials-modal').modal('show'); + $('#credentials-modal').modal('show'); } }, credentialsSaved: function (event) { if (event.status === 'success') { - if ($('#main\\:credentials-modal .text-danger').length === 0) { - $('#main\\:credentials-modal').modal('hide'); + if ($('#credentials-modal .text-danger').length === 0) { + $('#credentials-modal').modal('hide'); } } }, @@ -22,21 +22,25 @@ if (event.status === 'success') { checkSeparateCredentials(); } + }, + openConfirmDeleteModal: function (event) { + if (event.status === 'success') { + $('#modal-confirm-credentials-deletion').modal('show'); + } + }, + closeConfirmDeleteModal: function (event) { + if (event.status === 'success') { + $('#modal-confirm-credentials-deletion').modal('hide'); + } } }; $(document).ready(function () { - $('body').on('show.bs.modal', '#main\\:credentials-modal', function ( ) { + $('body').on('show.bs.modal', '#credentials-modal', function ( ) { checkSeparateCredentials(); }); -// $('body').on('shown.bs.modal', '#main\\:credentials-modal', function ( ) { -// $.post(TSM.getRestPath("credentialsDialog?opened=true")); -// }); -// $('body').on('hidden.bs.modal', '#main\\:credentials-modal', function ( ) { -// $.post(TSM.getRestPath("credentialsDialog?opened=false")); -// }); - $('body').on('keyup', '#main\\:credentials-modal input', function (event) { + $('body').on('keyup', '#credentials-modal input', function (event) { if (event.keyCode === 13) { $('#main\\:save-credentials').click(); event.preventDefault(); diff --git a/TASMAN-webapp/src/main/webapp/resources/tsm_components/print_credentials.xhtml b/TASMAN-webapp/src/main/webapp/resources/tsm_components/print_credentials.xhtml new file mode 100644 index 0000000..cbcf1a9 --- /dev/null +++ b/TASMAN-webapp/src/main/webapp/resources/tsm_components/print_credentials.xhtml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<html xmlns="http://www.w3.org/1999/xhtml" + xmlns:composite="http://java.sun.com/jsf/composite"> + + <composite:interface> + <composite:attribute name="credentials" type="it.inaf.ia2.tsm.datalayer.Credentials" required="true" /> + </composite:interface> + + <composite:implementation> + (${cc.attrs.credentials.databaseType eq 'MYSQL' ? 'MySQL' : 'Postgres'}) ${cc.attrs.credentials.hostname}:${cc.attrs.credentials.port} ${cc.attrs.credentials.username} + </composite:implementation> +</html> diff --git a/TASMAN-webapp/src/main/webapp/schemaSelection.xhtml b/TASMAN-webapp/src/main/webapp/schemaSelection.xhtml deleted file mode 100644 index c547e56..0000000 --- a/TASMAN-webapp/src/main/webapp/schemaSelection.xhtml +++ /dev/null @@ -1,127 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<ui:composition template="/WEB-INF/templates/master.xhtml" - xmlns="http://www.w3.org/1999/xhtml" - xmlns:f="http://java.sun.com/jsf/core" - xmlns:h="http://java.sun.com/jsf/html" - xmlns:ui="http://java.sun.com/jsf/facelets" - xmlns:tsm_components="http://xmlns.jcp.org/jsf/composite/tsm_components"> - <ui:define name="title">TASMAN - Schemata selection page</ui:define> - <ui:define name="scripts"> - <h:outputScript library="js" name="ucd-editor.js"></h:outputScript> - <h:outputScript library="js" name="async-loader.js"></h:outputScript> - <script>TSM.asyncLoader.init(#{schemaSelection.loading});</script> - </ui:define> - <ui:define name="content"> - - <f:event listener="#{loggedInChecker.checkFromNonIndex()}" type="preRenderView" /> - <f:event listener="#{schemaSelection.onPageLoad()}" type="preRenderView" /> - - <h:form id="main"> - - <tsm_components:user_navbar /> - - <div class="container"> - <h1 class="text-center">Schemata selection page</h1> - <br/> - - <f:passThroughAttribute name="autocomplete" value="off" /> - <div class="panel panel-default col-sm-10 col-sm-offset-1"> - <div class="panel-body"> - <div class="row"> - <div class="col-sm-2 text-right"> - <strong>Action:</strong> - </div> - <div class="form-inline col-sm-10"> - <h:selectOneRadio value="#{schemaSelection.selectedRadioOption}"> - <f:selectItem itemValue="edit" itemLabel="Edit existing" /> - <f:selectItem itemValue="create" itemLabel="Create new" /> - <f:ajax event="click" render="main:radioPanels"></f:ajax> - </h:selectOneRadio> - </div> - </div> - <br/> - - <h:panelGroup id="radioPanels"> - <!-- Edit --> - <h:panelGroup rendered="#{schemaSelection.selectedRadioOption eq 'edit'}"> - <div id="editContainer"> - <div class="form-group"> - <h:outputLabel for="selectedTAPSchema">Tap Schema:</h:outputLabel> - <h:selectOneMenu value="#{schemaSelection.selectedTAPSchema}" id="selectedTAPSchema" class="form-control"> - <f:selectItems value="#{schemaSelection.allTAPSchemas}"></f:selectItems> - <f:ajax event="change" render="main:exposedSchemas" listener="#{schemaSelection.selectedTAPSchemaChanged}"></f:ajax> - </h:selectOneMenu> - </div> - <div class="form-group" id="exposedDatabasesWrapper"> - <label class="control-label">Exposed databases:</label> - - <p class="form-control-static" id="exposed-schemas"> - <h:panelGroup id="exposedSchemas">#{schemaSelection.exposedSchemas}</h:panelGroup> - </p> - </div> - <div class="form-group"> - <h:commandButton value="Edit Tapschema" class="btn btn-primary" action="#{schemaSelection.edit()}"> - <f:ajax execute="@form" render="@form" onevent="TSM.asyncLoader.startChecking" /> - </h:commandButton> - </div> - </div> - </h:panelGroup> - - <!-- Create --> - <h:panelGroup rendered="#{schemaSelection.selectedRadioOption eq 'create'}"> - <div id="createContainer"> - <div class="form-group"> - <h:outputLabel for="tapschemaName">Name:</h:outputLabel> - <h:inputText id="tapschemaName" value="#{schemaSelection.tapSchemaName}" class="form-control" validator="#{schemaSelection.validateTapSchemaName}" /> - <h:message for="tapschemaName" class="text-danger validation-message"></h:message> - </div> - - <div class="form-group"> - <h:outputLabel for="tapschemaVersion">Version:</h:outputLabel> - <h:selectOneMenu id="tapschemaVersion" value="#{schemaSelection.version}" class="form-control" required="true" requiredMessage="Select version"> - <f:selectItem itemValue="#{null}" itemLabel="Select..." noSelectionOption="true" /> - <f:selectItems value="#{schemaSelection.versions}" var="v" itemLabel="TAP_SCHEMA #{v}" itemValue="#{v}" /> - </h:selectOneMenu> - <h:message for="tapschemaVersion" class="text-danger validation-message"></h:message> - </div> - - <div class="form-group"> - <h:outputLabel for="selectedSchemas">Databases to expose:</h:outputLabel> - <h:selectManyListbox value="#{schemaSelection.selectedSchemas}" id="selectedSchemas" class="form-control" size="7" validatorMessage="Select at least one schema"> - <f:selectItems value="#{schemaSelection.allSchemas}"></f:selectItems> - <f:validateRequired></f:validateRequired> - </h:selectManyListbox> - <h:message for="selectedSchemas" class="text-danger validation-message"></h:message> - </div> - - <div class="form-group"> - <h:commandButton value="Create TAP_SCHEMA" class="btn btn-primary" action="#{schemaSelection.create()}"> - <f:ajax execute="@form" render="@form" onevent="TSM.asyncLoader.startChecking" /> - </h:commandButton> - </div> - </div> - </h:panelGroup> - </h:panelGroup> - </div> - </div> - - <ui:remove> - <div class="row"> - <div class="col-sm-10 col-sm-offset-1"> - <h:commandLink action="#{schemaSelection.logout()}" class="btn btn-danger pull-right" immediate="true"> - <span class="glyphicon glyphicon-log-out"></span> - Close session - </h:commandLink> - </div> - </div> - </ui:remove> - </div> - - <tsm_components:ucd_editor id="ucd-editor" /> - </h:form> - - <h:form id="async-loader" class="hide"> - <h:commandButton action="#{schemaSelection.openLoaded()}" id="open-loaded" /> - </h:form> - </ui:define> -</ui:composition> \ No newline at end of file diff --git a/TASMAN-webapp/src/main/webapp/tapSchemaEditing.xhtml b/TASMAN-webapp/src/main/webapp/tapSchemaEditing.xhtml index aa37b0f..d36e1df 100644 --- a/TASMAN-webapp/src/main/webapp/tapSchemaEditing.xhtml +++ b/TASMAN-webapp/src/main/webapp/tapSchemaEditing.xhtml @@ -11,7 +11,7 @@ <h:outputScript library="js" name="edit-tapschema.js"></h:outputScript> <h:outputScript library="js" name="ucd-editor.js"></h:outputScript> <h:outputScript library="js" name="async-loader.js"></h:outputScript> - <script>TSM.asyncLoader.init(#{schemaSelection.loading});</script> + <script>TSM.asyncLoader.init(#{tapSchemaLoader.loading});</script> </ui:define> <ui:define name="content"> <f:event listener="#{loggedInChecker.checkFromNonIndex()}" type="preRenderView" /> @@ -852,7 +852,7 @@ </div> <h:form id="async-loader" class="hide"> - <h:commandButton action="#{schemaSelection.openLoaded()}" id="open-loaded" /> + <h:commandButton action="#{tapSchemaLoader.openLoaded()}" id="open-loaded" /> </h:form> </ui:define> </ui:composition> \ No newline at end of file -- GitLab