Java tutorial
/* * Copyright (C) 2005-2013 ManyDesigns srl. All rights reserved. * http://www.manydesigns.com/ * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 3 of * the License, or (at your option) any later version. * * This software 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package com.manydesigns.portofino.actions.admin.appwizard; import groovy.text.SimpleTemplateEngine; import groovy.text.Template; import groovy.text.TemplateEngine; import java.awt.Color; import java.io.File; import java.io.FileWriter; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import liquibase.database.DatabaseFactory; import liquibase.database.jvm.JdbcConnection; import net.sourceforge.stripes.action.Before; import net.sourceforge.stripes.action.DefaultHandler; import net.sourceforge.stripes.action.ForwardResolution; import net.sourceforge.stripes.action.RedirectResolution; import net.sourceforge.stripes.action.Resolution; import net.sourceforge.stripes.action.UrlBinding; import org.apache.commons.configuration.Configuration; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.exception.ExceptionUtils; import org.apache.shiro.SecurityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ListMultimap; import com.google.common.collect.Multimap; import com.manydesigns.elements.ElementsThreadLocals; import com.manydesigns.elements.Mode; import com.manydesigns.elements.annotations.LabelI18N; import com.manydesigns.elements.annotations.Multiline; import com.manydesigns.elements.annotations.Password; import com.manydesigns.elements.fields.BooleanField; import com.manydesigns.elements.fields.Field; import com.manydesigns.elements.fields.SelectField; import com.manydesigns.elements.fields.TextField; import com.manydesigns.elements.forms.FieldSet; import com.manydesigns.elements.forms.Form; import com.manydesigns.elements.forms.FormBuilder; import com.manydesigns.elements.forms.TableForm; import com.manydesigns.elements.forms.TableFormBuilder; import com.manydesigns.elements.messages.SessionMessages; import com.manydesigns.elements.options.DefaultSelectionProvider; import com.manydesigns.elements.reflection.ClassAccessor; import com.manydesigns.elements.reflection.JavaClassAccessor; import com.manydesigns.elements.reflection.PropertyAccessor; import com.manydesigns.elements.util.RandomUtil; import com.manydesigns.elements.util.Util; import com.manydesigns.portofino.actions.forms.ConnectionProviderForm; import com.manydesigns.portofino.actions.forms.SelectableSchema; import com.manydesigns.portofino.buttons.annotations.Button; import com.manydesigns.portofino.buttons.annotations.Buttons; import com.manydesigns.portofino.database.platforms.DatabasePlatform; import com.manydesigns.portofino.database.platforms.DatabasePlatformsRegistry; import com.manydesigns.portofino.di.Inject; import com.manydesigns.portofino.dispatcher.DispatcherLogic; import com.manydesigns.portofino.dispatcher.PageInstance; import com.manydesigns.portofino.logic.SecurityLogic; import com.manydesigns.portofino.model.Annotation; import com.manydesigns.portofino.model.Model; import com.manydesigns.portofino.model.database.Column; import com.manydesigns.portofino.model.database.ConnectionProvider; import com.manydesigns.portofino.model.database.Database; import com.manydesigns.portofino.model.database.DatabaseLogic; import com.manydesigns.portofino.model.database.ForeignKey; import com.manydesigns.portofino.model.database.IncrementGenerator; import com.manydesigns.portofino.model.database.JdbcConnectionProvider; import com.manydesigns.portofino.model.database.JndiConnectionProvider; import com.manydesigns.portofino.model.database.ModelSelectionProvider; import com.manydesigns.portofino.model.database.PrimaryKeyColumn; import com.manydesigns.portofino.model.database.Reference; import com.manydesigns.portofino.model.database.Schema; import com.manydesigns.portofino.model.database.Table; import com.manydesigns.portofino.modules.BaseModule; import com.manydesigns.portofino.modules.DatabaseModule; import com.manydesigns.portofino.modules.PageactionsModule; import com.manydesigns.portofino.pageactions.AbstractPageAction; import com.manydesigns.portofino.pageactions.calendar.configuration.CalendarConfiguration; import com.manydesigns.portofino.pageactions.crud.configuration.CrudConfiguration; import com.manydesigns.portofino.pageactions.crud.configuration.CrudProperty; import com.manydesigns.portofino.pages.ChildPage; import com.manydesigns.portofino.pages.Group; import com.manydesigns.portofino.pages.Page; import com.manydesigns.portofino.pages.Permissions; import com.manydesigns.portofino.persistence.Persistence; import com.manydesigns.portofino.security.AccessLevel; import com.manydesigns.portofino.security.RequiresAdministrator; import com.manydesigns.portofino.sync.DatabaseSyncer; /** * @author Paolo Predonzani - paolo.predonzani@manydesigns.com * @author Angelo Lupo - angelo.lupo@manydesigns.com * @author Giampiero Granatella - giampiero.granatella@manydesigns.com * @author Alessio Stalla - alessio.stalla@manydesigns.com */ @RequiresAdministrator @UrlBinding(ApplicationWizard.URL_BINDING) public class ApplicationWizard extends AbstractPageAction { public static final String copyright = "Copyright (c) 2005-2013, ManyDesigns srl"; public static final String URL_BINDING = "/actions/admin/wizard"; public static final String JDBC = "JDBC"; public static final String JNDI = "JNDI"; @SuppressWarnings({ "RedundantStringConstructorCall" }) public static final String NO_LINK_TO_PARENT = new String(); public static final int LARGE_RESULT_SET_THRESHOLD = 10000; protected int step = 0; // Forms and fields protected SelectField connectionProviderField; protected Form jndiCPForm; protected Form jdbcCPForm; protected Form connectionProviderForm; protected Form userAndGroupTablesForm; protected Form userManagementSetupForm; protected String connectionProviderType; protected String connectionProviderName; protected ConnectionProvider connectionProvider; protected Database database; public TableForm schemasForm; protected List<SelectableSchema> selectableSchemas; public TableForm rootsForm; protected List<SelectableRoot> selectableRoots = new ArrayList<SelectableRoot>(); protected String generationStrategy = "AUTO"; protected BooleanField generateCalendarField; // hongliangpan modify ?? protected boolean generateCalendar = false; // Users protected String userTableName; protected String groupTableName; protected String userGroupTableName; protected String userNameProperty; protected String userEmailProperty; protected String userTokenProperty; protected String userIdProperty; protected String userPasswordProperty; protected String encryptionAlgorithm; protected String groupIdProperty; protected String groupNameProperty; protected String groupLinkProperty; protected String userLinkProperty; protected String adminGroupName; protected List<Table> roots; protected ListMultimap<Table, Reference> children; protected List<Table> allTables; protected Table userTable; protected Table groupTable; protected Table userGroupTable; protected int maxColumnsInSummary = 5; protected int maxDepth = 5; protected int depth; private final String databaseSessionKey = getClass().getName() + ".database"; public final static String[] JDBC_CP_FIELDS = { "databaseName", "driver", "url", "username", "password" }; public final static String[] JNDI_CP_FIELDS = { "databaseName", "jndiResource" }; // ************************************************************************** // Injections // ************************************************************************** @Inject(DatabaseModule.PERSISTENCE) public Persistence persistence; @Inject(PageactionsModule.PAGES_DIRECTORY) public File pagesDir; @Inject(BaseModule.APPLICATION_DIRECTORY) public File appDir; public static final Logger logger = LoggerFactory.getLogger(ApplicationWizard.class); @DefaultHandler @Button(list = "select-schemas", key = "<<previous", order = 1) public Resolution start() { buildCPForms(); context.getRequest().getSession().removeAttribute(databaseSessionKey); return createConnectionProviderForm(); } protected Resolution createConnectionProviderForm() { step = 0; return new ForwardResolution("/m/wizard/connection-provider.jsp"); } @Before public void prepare() { connectionProviderName = context.getRequest().getParameter("connectionProviderName"); } protected void buildCPForms() { DefaultSelectionProvider connectionProviderSP = new DefaultSelectionProvider("connectionProviderName"); for (Database db : persistence.getModel().getDatabases()) { ConnectionProvider cp = db.getConnectionProvider(); if (!ConnectionProvider.STATUS_ERROR.equals(cp.getStatus())) { connectionProviderSP.appendRow(db.getDatabaseName(), db.getDatabaseName() + " (" + cp.getDatabasePlatform().getDescription() + ")", true); } } ClassAccessor classAccessor = JavaClassAccessor.getClassAccessor(ApplicationWizard.class); try { connectionProviderField = new SelectField(classAccessor.getProperty("connectionProviderName"), connectionProviderSP, Mode.EDIT, null); connectionProviderField.setLabel(ElementsThreadLocals.getText("use.an.existing.database.connection")); connectionProviderField.setComboLabel("--"); } catch (NoSuchFieldException e) { throw new Error(e); } jndiCPForm = new FormBuilder(ConnectionProviderForm.class).configFields(JNDI_CP_FIELDS).configPrefix("jndi") .configMode(Mode.CREATE).build(); DefaultSelectionProvider driverSelectionProvider = new DefaultSelectionProvider("name"); // database platforms DatabasePlatformsRegistry manager = persistence.getDatabasePlatformsRegistry(); DatabasePlatform[] databasePlatforms = manager.getDatabasePlatforms(); for (DatabasePlatform dp : databasePlatforms) { if (DatabasePlatform.STATUS_OK.equals(dp.getStatus())) { driverSelectionProvider.appendRow(dp.getStandardDriverClassName(), dp.getDescription(), true); } } jdbcCPForm = new FormBuilder(ConnectionProviderForm.class).configFields(JDBC_CP_FIELDS).configPrefix("jdbc") .configMode(Mode.CREATE).configSelectionProvider(driverSelectionProvider, "driver").build(); jdbcCPForm.findFieldByPropertyName("driver") .setHelp(ElementsThreadLocals.getText("additional.drivers.can.be.downloaded")); // Handle back jndiCPForm.readFromRequest(context.getRequest()); jdbcCPForm.readFromRequest(context.getRequest()); connectionProviderField.readFromObject(this); connectionProviderField.readFromRequest(context.getRequest()); } @Button(list = "user-management", key = "<<previous", order = 1) public Resolution backToSelectSchemas() { context.getRequest().getSession().removeAttribute(databaseSessionKey); return configureConnectionProvider(); } @Button(list = "connection-provider", key = "next>>", order = 1, type = Button.TYPE_PRIMARY) public Resolution configureConnectionProvider() { buildCPForms(); if (connectionProviderField.validate()) { connectionProviderField.writeToObject(this); } else { return createConnectionProviderForm(); } if (!isNewConnectionProvider()) { connectionProvider = DatabaseLogic.findDatabaseByName(persistence.getModel(), connectionProviderName) .getConnectionProvider(); return afterCreateConnectionProvider(); } if (JDBC.equals(connectionProviderType)) { connectionProvider = new JdbcConnectionProvider(); connectionProviderForm = jdbcCPForm; } else if (JNDI.equals(connectionProviderType)) { connectionProvider = new JndiConnectionProvider(); connectionProviderForm = jndiCPForm; } else { throw new Error("Unknown connection provider type: " + connectionProviderType); } Database database = new Database(); database.setConnectionProvider(connectionProvider); connectionProvider.setDatabase(database); ConnectionProviderForm edit = new ConnectionProviderForm(database); connectionProviderForm.readFromRequest(context.getRequest()); if (connectionProviderForm.validate()) { connectionProviderForm.writeToObject(edit); Database existingDatabase = DatabaseLogic.findDatabaseByName(persistence.getModel(), edit.getDatabaseName()); if (existingDatabase != null) { SessionMessages.addErrorMessage(ElementsThreadLocals.getText("there.is.already.a.database.named._", edit.getDatabaseName())); return createConnectionProviderForm(); } return afterCreateConnectionProvider(); } else { return createConnectionProviderForm(); } } public Resolution afterCreateConnectionProvider() { try { configureEditSchemas(); } catch (Exception e) { logger.error("Couldn't read schema names from db", e); SessionMessages.addErrorMessage(ElementsThreadLocals.getText("couldnt.read.schema.names.from.db._", e)); return createConnectionProviderForm(); } return selectSchemasForm(); } protected Resolution selectSchemasForm() { step = 1; return new ForwardResolution("/m/wizard/select-schemas.jsp"); } protected void configureEditSchemas() throws Exception { connectionProvider.init(persistence.getDatabasePlatformsRegistry()); Connection conn = connectionProvider.acquireConnection(); logger.debug("Reading database metadata"); DatabaseMetaData metadata = conn.getMetaData(); List<String> schemaNamesFromDb = connectionProvider.getDatabasePlatform().getSchemaNames(metadata); connectionProvider.releaseConnection(conn); selectableSchemas = new ArrayList<SelectableSchema>(schemaNamesFromDb.size()); for (String schemaName : schemaNamesFromDb) { SelectableSchema schema = new SelectableSchema(schemaName, schemaNamesFromDb.size() == 1); selectableSchemas.add(schema); } schemasForm = new TableFormBuilder(SelectableSchema.class).configFields("selected", "schemaName") .configMode(Mode.EDIT).configNRows(selectableSchemas.size()).configPrefix("schemas_").build(); schemasForm.readFromObject(selectableSchemas); // Handle back schemasForm.readFromRequest(context.getRequest()); } @Buttons({ @Button(list = "select-schemas", key = "next>>", order = 2, type = Button.TYPE_PRIMARY), @Button(list = "select-user-fields", key = "<<previous", order = 1) }) public Resolution selectSchemas() { configureConnectionProvider(); schemasForm.readFromRequest(context.getRequest()); if (schemasForm.validate()) { schemasForm.writeToObject(selectableSchemas); boolean atLeastOneSelected = isAtLeastOneSchemaSelected(); if (atLeastOneSelected) { if (configureModelSchemas(false) == null) { return selectSchemasForm(); } return afterSelectSchemas(); } else { SessionMessages.addErrorMessage(ElementsThreadLocals.getText("select.at.least.a.schema")); return selectSchemasForm(); } } return selectSchemasForm(); } protected boolean isAtLeastOneSchemaSelected() { boolean atLeastOneSelected = false; for (SelectableSchema schema : selectableSchemas) { if (schema.selected) { atLeastOneSelected = true; break; } } return atLeastOneSelected; } protected void updateModelFailed(Exception e) { logger.error("Could not update model", e); SessionMessages.addErrorMessage( ElementsThreadLocals.getText("could.not.save.model._", ExceptionUtils.getRootCauseMessage(e))); if (isNewConnectionProvider()) { persistence.getModel().getDatabases().remove(connectionProvider.getDatabase()); } persistence.initModel(); } protected Database configureModelSchemas(boolean alwaysUseExistingModel) { Model refModel; if (!alwaysUseExistingModel && isNewConnectionProvider()) { refModel = new Model(); } else { refModel = persistence.getModel(); } List<Schema> tempSchemas = new ArrayList<Schema>(); Database database = connectionProvider.getDatabase(); for (SelectableSchema schema : selectableSchemas) { Schema modelSchema = DatabaseLogic.findSchemaByName(database, schema.schemaName); if (schema.selected) { if (modelSchema == null) { modelSchema = new Schema(); modelSchema.setSchemaName(schema.schemaName); modelSchema.setDatabase(database); database.getSchemas().add(modelSchema); tempSchemas.add(modelSchema); } } } this.database = (Database) context.getRequest().getSession().getAttribute(databaseSessionKey); if (this.database != null) { return this.database; } Database targetDatabase; DatabaseSyncer dbSyncer = new DatabaseSyncer(connectionProvider); try { targetDatabase = dbSyncer.syncDatabase(refModel); } catch (Exception e) { logger.error(e.getMessage(), e); SessionMessages.addErrorMessage(ElementsThreadLocals.getText("error.in.database.synchronization._", e)); return null; } finally { database.getSchemas().removeAll(tempSchemas); connectionProvider.setDatabase(database); // Restore } Model model = new Model(); model.getDatabases().add(targetDatabase); model.init(); this.database = targetDatabase; context.getRequest().getSession().setAttribute(databaseSessionKey, this.database); return targetDatabase; } public boolean isNewConnectionProvider() { return StringUtils.isEmpty(connectionProviderName); } public Resolution afterSelectSchemas() { children = ArrayListMultimap.create(); allTables = new ArrayList<Table>(); roots = determineRoots(children, allTables); Collections.sort(allTables, new Comparator<Table>() { public int compare(Table o1, Table o2) { return o1.getQualifiedName().compareToIgnoreCase(o2.getQualifiedName()); } }); rootsForm = new TableFormBuilder(SelectableRoot.class).configFields("selected", "tableName") .configMode(Mode.EDIT).configNRows(selectableRoots.size()).configPrefix("roots_").build(); rootsForm.readFromObject(selectableRoots); try { ClassAccessor classAccessor = JavaClassAccessor.getClassAccessor(getClass()); PropertyAccessor userPropertyAccessor = classAccessor.getProperty("userTableName"); PropertyAccessor groupPropertyAccessor = classAccessor.getProperty("groupTableName"); PropertyAccessor userGroupPropertyAccessor = classAccessor.getProperty("userGroupTableName"); DefaultSelectionProvider selectionProvider = new DefaultSelectionProvider("tableName"); int schemaCount = 0; for (SelectableSchema schema : selectableSchemas) { if (schema.selected) { schemaCount++; } } for (Table table : allTables) { String tableName; if (schemaCount > 1) { tableName = table.getSchemaName() + "." + table.getTableName(); } else { tableName = table.getTableName(); } selectionProvider.appendRow(table.getQualifiedName(), tableName, true); } Mode mode = Mode.CREATE; Field userTableField = new SelectField(userPropertyAccessor, selectionProvider, mode, ""); Field groupTableField = new SelectField(groupPropertyAccessor, selectionProvider, mode, ""); Field userGroupTableField = new SelectField(userGroupPropertyAccessor, selectionProvider, mode, ""); userAndGroupTablesForm = new Form(mode); FieldSet fieldSet = new FieldSet(ElementsThreadLocals.getText("users.and.groups.tables"), 1, mode); fieldSet.add(userTableField); fieldSet.add(groupTableField); fieldSet.add(userGroupTableField); userAndGroupTablesForm.add(fieldSet); // Handle back userAndGroupTablesForm.readFromRequest(context.getRequest()); } catch (NoSuchFieldException e) { throw new Error(e); } return userManagementForm(); } protected Resolution userManagementForm() { step = 2; return new ForwardResolution("/m/wizard/user-management.jsp"); } @Button(list = "user-management", key = "next>>", order = 2, type = Button.TYPE_PRIMARY) public Resolution setupUserManagement() { selectSchemas(); userAndGroupTablesForm.readFromRequest(context.getRequest()); userAndGroupTablesForm.writeToObject(this); if (!StringUtils.isEmpty(userTableName)) { Model tmpModel = new Model(); tmpModel.getDatabases().add(database); String[] name = DatabaseLogic.splitQualifiedTableName(userTableName); userTable = DatabaseLogic.findTableByName(tmpModel, name[0], name[1], name[2]); if (!StringUtils.isEmpty(groupTableName)) { name = DatabaseLogic.splitQualifiedTableName(groupTableName); groupTable = DatabaseLogic.findTableByName(tmpModel, name[0], name[1], name[2]); } if (!StringUtils.isEmpty(userGroupTableName)) { name = DatabaseLogic.splitQualifiedTableName(userGroupTableName); userGroupTable = DatabaseLogic.findTableByName(tmpModel, name[0], name[1], name[2]); } createUserManagementSetupForm(); return selectUserFieldsForm(); } else { return selectTablesForm(); } } protected void createUserManagementSetupForm() { DefaultSelectionProvider userSelectionProvider = new DefaultSelectionProvider(""); for (Column column : userTable.getColumns()) { userSelectionProvider.appendRow(column.getActualPropertyName(), column.getActualPropertyName(), true); } DefaultSelectionProvider algoSelectionProvider = new DefaultSelectionProvider(""); algoSelectionProvider.appendRow("plaintext", ElementsThreadLocals.getText("plain.text"), true); algoSelectionProvider.appendRow("md5Base64", ElementsThreadLocals.getText("md5.base64.encoded"), true); algoSelectionProvider.appendRow("md5Hex", ElementsThreadLocals.getText("md5.hex.encoded"), true); algoSelectionProvider.appendRow("sha1Base64", ElementsThreadLocals.getText("sha1.base64.encoded.portofino3"), true); algoSelectionProvider.appendRow("sha1Hex", ElementsThreadLocals.getText("sha1.hex.encoded"), true); try { ClassAccessor classAccessor = JavaClassAccessor.getClassAccessor(getClass()); Mode mode = Mode.CREATE; userManagementSetupForm = new Form(mode); PropertyAccessor propertyAccessor = classAccessor.getProperty("userIdProperty"); Field userIdPropertyField = new SelectField(propertyAccessor, userSelectionProvider, mode, ""); userIdPropertyField.setRequired(true); propertyAccessor = classAccessor.getProperty("userNameProperty"); Field userNamePropertyField = new SelectField(propertyAccessor, userSelectionProvider, mode, ""); userNamePropertyField.setRequired(true); propertyAccessor = classAccessor.getProperty("userPasswordProperty"); Field userPasswordPropertyField = new SelectField(propertyAccessor, userSelectionProvider, mode, ""); userPasswordPropertyField.setRequired(true); propertyAccessor = classAccessor.getProperty("encryptionAlgorithm"); Field encryptionAlgorithmField = new SelectField(propertyAccessor, algoSelectionProvider, mode, ""); encryptionAlgorithmField.setRequired(true); propertyAccessor = classAccessor.getProperty("userEmailProperty"); Field userEmailPropertyField = new SelectField(propertyAccessor, userSelectionProvider, mode, ""); userEmailPropertyField.setRequired(false); propertyAccessor = classAccessor.getProperty("userTokenProperty"); Field userTokenPropertyField = new SelectField(propertyAccessor, userSelectionProvider, mode, ""); userTokenPropertyField.setRequired(false); FieldSet uFieldSet = new FieldSet(ElementsThreadLocals.getText("users.table.setup"), 1, mode); uFieldSet.add(userIdPropertyField); uFieldSet.add(userNamePropertyField); uFieldSet.add(userPasswordPropertyField); uFieldSet.add(encryptionAlgorithmField); uFieldSet.add(userEmailPropertyField); uFieldSet.add(userTokenPropertyField); userManagementSetupForm.add(uFieldSet); userIdProperty = userTable.getPrimaryKey().getColumns().get(0).getActualPropertyName(); if (groupTable != null && userGroupTable != null) { DefaultSelectionProvider groupSelectionProvider = new DefaultSelectionProvider(""); for (Column column : groupTable.getColumns()) { groupSelectionProvider.appendRow(column.getActualPropertyName(), column.getActualPropertyName(), true); } DefaultSelectionProvider userGroupSelectionProvider = new DefaultSelectionProvider(""); for (Column column : userGroupTable.getColumns()) { userGroupSelectionProvider.appendRow(column.getActualPropertyName(), column.getActualPropertyName(), true); } propertyAccessor = classAccessor.getProperty("groupIdProperty"); Field groupIdPropertyField = new SelectField(propertyAccessor, groupSelectionProvider, mode, ""); groupIdPropertyField.setRequired(true); propertyAccessor = classAccessor.getProperty("groupNameProperty"); Field groupNamePropertyField = new SelectField(propertyAccessor, groupSelectionProvider, mode, ""); groupNamePropertyField.setRequired(true); propertyAccessor = classAccessor.getProperty("groupLinkProperty"); Field groupLinkPropertyField = new SelectField(propertyAccessor, userGroupSelectionProvider, mode, ""); groupLinkPropertyField.setRequired(true); propertyAccessor = classAccessor.getProperty("userLinkProperty"); Field userLinkPropertyField = new SelectField(propertyAccessor, userGroupSelectionProvider, mode, ""); userLinkPropertyField.setRequired(true); propertyAccessor = classAccessor.getProperty("adminGroupName"); Field adminGroupNameField = new TextField(propertyAccessor, mode); FieldSet gFieldSet = new FieldSet(ElementsThreadLocals.getText("groups.tables.setup"), 1, mode); gFieldSet.add(groupIdPropertyField); gFieldSet.add(groupNamePropertyField); gFieldSet.add(groupLinkPropertyField); gFieldSet.add(userLinkPropertyField); gFieldSet.add(adminGroupNameField); userManagementSetupForm.add(gFieldSet); groupIdProperty = groupTable.getPrimaryKey().getColumns().get(0).getActualPropertyName(); for (ForeignKey fk : userGroupTable.getForeignKeys()) { for (Reference ref : fk.getReferences()) { if (ref.getActualToColumn().getTable().equals(userTable)) { userLinkProperty = ref.getActualFromColumn().getActualPropertyName(); } else if (ref.getActualToColumn().getTable().equals(groupTable)) { groupLinkProperty = ref.getActualFromColumn().getActualPropertyName(); } } } } userManagementSetupForm.readFromObject(this); } catch (NoSuchFieldException e) { throw new Error(e); } } @Button(list = "select-user-fields", key = "next>>", order = 2, type = Button.TYPE_PRIMARY) public Resolution selectUserFields() { setupUserManagement(); if (userTable != null) { userManagementSetupForm.readFromRequest(context.getRequest()); if (userManagementSetupForm.validate()) { userManagementSetupForm.writeToObject(this); return selectTablesForm(); } else { return selectUserFieldsForm(); } } else { return selectTablesForm(); } } protected Resolution selectUserFieldsForm() { step = 3; return new ForwardResolution("/m/wizard/select-user-fields.jsp"); } protected Resolution selectTablesForm() { step = (userTable == null) ? 3 : 4; setupCalendarField(); return new ForwardResolution("/m/wizard/select-tables.jsp"); } protected void setupCalendarField() { ClassAccessor classAccessor = JavaClassAccessor.getClassAccessor(ApplicationWizard.class); try { generateCalendarField = new BooleanField(classAccessor.getProperty("generateCalendar"), Mode.EDIT); generateCalendarField.setLabel(ElementsThreadLocals.getText("generate.a.calendar.page")); generateCalendarField.readFromObject(this); } catch (NoSuchFieldException e) { throw new Error(e); } } protected List<Table> determineRoots(Multimap<Table, Reference> children, List<Table> allTables) { List<Table> roots = new ArrayList<Table>(); for (SelectableSchema selectableSchema : selectableSchemas) { if (selectableSchema.selected) { Schema schema = DatabaseLogic.findSchemaByName(database, selectableSchema.schemaName); roots.addAll(schema.getTables()); } } for (Iterator<Table> it = roots.iterator(); it.hasNext();) { Table table = it.next(); if (table.getPrimaryKey() == null) { it.remove(); continue; } allTables.add(table); boolean removed = false; // Did we already remove the table from the list of roots? boolean selected = false; // Is the table selected as a root? Note that selected => known boolean known = false; // Is the table in the list of selectable roots? for (SelectableRoot root : selectableRoots) { if (root.tableName.equals(table.getSchemaName() + "." + table.getTableName())) { selected = root.selected; known = true; break; } } if (known && !selected) { it.remove(); removed = true; } if (!table.getForeignKeys().isEmpty()) { for (ForeignKey fk : table.getForeignKeys()) { for (Reference ref : fk.getReferences()) { Column column = ref.getActualToColumn(); if (column.getTable() != table) { children.put(column.getTable(), ref); // TODO potrebbe essere un ciclo nel grafo... if (!selected && !removed) { it.remove(); removed = true; } } } } } if (!table.getSelectionProviders().isEmpty()) { for (ModelSelectionProvider sp : table.getSelectionProviders()) { for (Reference ref : sp.getReferences()) { Column column = ref.getActualToColumn(); if (column != null && column.getTable() != table) { children.put(column.getTable(), ref); // TODO potrebbe essere un ciclo nel grafo... if (!selected && !removed) { it.remove(); removed = true; } } } } } if (!known) { SelectableRoot root = new SelectableRoot(table.getSchemaName() + "." + table.getTableName(), !removed); selectableRoots.add(root); } } Collections.sort(selectableRoots, new Comparator<SelectableRoot>() { public int compare(SelectableRoot o1, SelectableRoot o2) { return o1.tableName.compareTo(o2.tableName); } }); return roots; } @Button(list = "select-tables", key = "next>>", order = 2, type = Button.TYPE_PRIMARY) public Resolution selectTables() { selectUserFields(); rootsForm.readFromRequest(context.getRequest()); rootsForm.writeToObject(selectableRoots); // Recalc roots afterSelectSchemas(); if (roots.isEmpty()) { SessionMessages.addWarningMessage(ElementsThreadLocals.getText("no.page.will.be.generated")); } return buildAppForm(); } @Button(list = "select-tables", key = "<<previous", order = 1) public Resolution goBackFromSelectTables() { selectUserFields(); if (userTable == null) { return userManagementForm(); } else { return selectUserFieldsForm(); } } protected Resolution buildAppForm() { step = (userTable == null) ? 4 : 5; setupCalendarField(); generateCalendarField.readFromRequest(context.getRequest()); generateCalendarField.writeToObject(this); return new ForwardResolution("/m/wizard/build-app.jsp"); } @Button(list = "build-app", key = "<<previous", order = 1) public Resolution returnToSelectTables() { selectTables(); return selectTablesForm(); } @Button(list = "build-app", key = "finish", order = 2, type = Button.TYPE_PRIMARY) public Resolution buildApplication() { selectTables(); Database oldDatabase = DatabaseLogic.findDatabaseByName(persistence.getModel(), database.getDatabaseName()); if (oldDatabase != null) { persistence.getModel().getDatabases().remove(oldDatabase); } persistence.getModel().getDatabases().add(database); connectionProvider.setDatabase(database); database.setConnectionProvider(connectionProvider); try { persistence.initModel(); } catch (Exception e) { updateModelFailed(e); return buildAppForm(); } if (!generationStrategy.equals("NO")) { if (generationStrategy.equals("AUTO")) { generateCalendar = true; } try { TemplateEngine engine = new SimpleTemplateEngine(); Template template = engine.createTemplate(ApplicationWizard.class.getResource("CrudPage.groovy")); List<ChildPage> childPages = new ArrayList<ChildPage>(); for (Table table : roots) { File dir = new File(pagesDir, table.getActualEntityName()); depth = 1; createCrudPage(dir, table, childPages, template); } if (userTable != null) { setupUserPages(childPages, template); } if (generateCalendar) { setupCalendar(childPages); } Page rootPage = DispatcherLogic.getPage(pagesDir); Collections.sort(childPages, new Comparator<ChildPage>() { public int compare(ChildPage o1, ChildPage o2) { return o1.getName().compareToIgnoreCase(o2.getName()); } }); rootPage.getLayout().getChildPages().addAll(childPages); DispatcherLogic.savePage(pagesDir, rootPage); } catch (Exception e) { logger.error("Error while creating pages", e); SessionMessages.addErrorMessage(ElementsThreadLocals.getText("could.not.create.pages._", e)); return buildAppForm(); } } if (userTable != null) { setupUsers(); } try { persistence.initModel(); persistence.saveXmlModel(); } catch (Exception e) { updateModelFailed(e); return buildAppForm(); } if (userTable != null) { SecurityUtils.getSubject().logout(); context.getRequest().getSession().invalidate(); SessionMessages.addWarningMessage(ElementsThreadLocals .getText("user.management.has.been.configured.please.edit.security.groovy")); // ShiroUtils.clearCache(SecurityUtils.getSubject().getPrincipals()); } SessionMessages.addInfoMessage(ElementsThreadLocals.getText("application.created")); context.getRequest().getSession().removeAttribute(databaseSessionKey); return new RedirectResolution("/"); } protected void setupCalendar(List<ChildPage> childPages) throws Exception { List<List<String>> calendarDefinitions = new ArrayList<List<String>>(); Color[] colors = { Color.RED, new Color(64, 128, 255), Color.CYAN.darker(), Color.GRAY, Color.GREEN.darker(), Color.ORANGE, Color.YELLOW.darker(), Color.MAGENTA.darker(), Color.PINK }; int colorIndex = 0; for (Table table : allTables) { List<Column> dateColumns = new ArrayList<Column>(); for (Column column : table.getColumns()) { if (column.getActualJavaType() != null && Date.class.isAssignableFrom(column.getActualJavaType())) { dateColumns.add(column); } } if (!dateColumns.isEmpty()) { // ["Cal 1", "db1.schema1.table1", ["column1", "column2"], Color.RED] Color color = colors[colorIndex++ % colors.length]; List<String> calDef = new ArrayList<String>(); calDef.add('"' + Util.guessToWords(table.getActualEntityName()) + '"'); calDef.add('"' + table.getQualifiedName() + '"'); String cols = "["; boolean first = true; for (Column column : dateColumns) { if (first) { first = false; } else { cols += ", "; } cols += '"' + column.getActualPropertyName() + '"'; } cols += "]"; calDef.add(cols); calDef.add("new java.awt.Color(" + color.getRed() + ", " + color.getGreen() + ", " + color.getBlue() + ")"); calendarDefinitions.add(calDef); } } if (!calendarDefinitions.isEmpty()) { String calendarDefinitionsStr = "["; calendarDefinitionsStr += StringUtils.join(calendarDefinitions, ", "); calendarDefinitionsStr += "]"; String baseName = "calendar-" + connectionProvider.getDatabase().getDatabaseName(); File dir = new File(pagesDir, baseName); int retries = 1; while (dir.exists()) { retries++; dir = new File(pagesDir, baseName + "-" + retries); } if (dir.mkdirs()) { CalendarConfiguration configuration = new CalendarConfiguration(); DispatcherLogic.saveConfiguration(dir, configuration); Page page = new Page(); page.setId(RandomUtil.createRandomId()); String calendarTitle = "Calendar (" + connectionProvider.getDatabase().getDatabaseName() + ")"; if (retries > 1) { calendarTitle += " - " + retries; } page.setTitle(calendarTitle); page.setDescription(calendarTitle); DispatcherLogic.savePage(dir, page); File actionFile = new File(dir, "action.groovy"); try { TemplateEngine engine = new SimpleTemplateEngine(); Template template = engine .createTemplate(ApplicationWizard.class.getResource("CalendarPage.groovy")); Map<String, Object> bindings = new HashMap<String, Object>(); bindings.put("calendarDefinitions", calendarDefinitionsStr); FileWriter fw = new FileWriter(actionFile); template.make(bindings).writeTo(fw); IOUtils.closeQuietly(fw); } catch (Exception e) { logger.warn("Couldn't create calendar", e); SessionMessages.addWarningMessage("Couldn't create calendar: " + e); return; } ChildPage childPage = new ChildPage(); childPage.setName(dir.getName()); childPage.setShowInNavigation(true); childPages.add(childPage); } else { logger.warn("Couldn't create directory {}", dir.getAbsolutePath()); SessionMessages.addWarningMessage( ElementsThreadLocals.getText("couldnt.create.directory", dir.getAbsolutePath())); } } } protected void setupUserPages(List<ChildPage> childPages, Template template) throws Exception { if (!roots.contains(userTable)) { File dir = new File(pagesDir, userTable.getActualEntityName()); depth = 1; createCrudPage(dir, userTable, childPages, template); } Configuration conf = portofinoConfiguration; List<Reference> references = (List<Reference>) children.get(userTable); if (references != null) { for (Reference ref : references) { depth = 1; Column fromColumn = ref.getActualFromColumn(); Column toColumn = ref.getActualToColumn(); Table fromTable = fromColumn.getTable(); Table toTable = toColumn.getTable(); String entityName = fromTable.getActualEntityName(); List<Column> pkColumns = toTable.getPrimaryKey().getColumns(); if (!pkColumns.contains(toColumn)) { continue; } String linkToUserProperty = fromColumn.getActualPropertyName(); String childQuery = "from " + entityName + " where " + linkToUserProperty + " = %{#securityUtils.primaryPrincipal.id}" + " order by id desc"; String dirName = "my-" + entityName; boolean multipleRoles = isMultipleRoles(fromTable, ref, references); if (multipleRoles) { dirName += "-as-" + linkToUserProperty; } File dir = new File(pagesDir, dirName); String title = Util.guessToWords(dirName); Map<String, String> bindings = new HashMap<String, String>(); bindings.put("parentName", "securityUtils"); bindings.put("parentProperty", "primaryPrincipal.id"); bindings.put("linkToParentProperty", linkToUserProperty); Page page = createCrudPage(dir, fromTable, childQuery, childPages, template, bindings, title); if (page != null) { Group group = new Group(); group.setName(SecurityLogic.getAnonymousGroup(conf)); group.setAccessLevel(AccessLevel.DENY.name()); Permissions permissions = new Permissions(); permissions.getGroups().add(group); page.setPermissions(permissions); DispatcherLogic.savePage(dir, page); } } } } protected void setupUsers() { try { TemplateEngine engine = new SimpleTemplateEngine(); Template secTemplate = engine.createTemplate(ApplicationWizard.class.getResource("Security.groovy")); Map<String, String> bindings = new HashMap<String, String>(); bindings.put("databaseName", connectionProvider.getDatabase().getDatabaseName()); bindings.put("userTableEntityName", userTable.getActualEntityName()); bindings.put("userIdProperty", userIdProperty); bindings.put("userNameProperty", userNameProperty); bindings.put("passwordProperty", userPasswordProperty); bindings.put("userEmailProperty", userEmailProperty); bindings.put("userTokenProperty", userTokenProperty); bindings.put("groupTableEntityName", groupTable != null ? groupTable.getActualEntityName() : ""); bindings.put("groupIdProperty", StringUtils.defaultString(groupIdProperty)); bindings.put("groupNameProperty", StringUtils.defaultString(groupNameProperty)); bindings.put("userGroupTableEntityName", userGroupTable != null ? userGroupTable.getActualEntityName() : ""); bindings.put("groupLinkProperty", StringUtils.defaultString(groupLinkProperty)); bindings.put("userLinkProperty", StringUtils.defaultString(userLinkProperty)); bindings.put("adminGroupName", StringUtils.defaultString(adminGroupName)); bindings.put("encryptionAlgorithm", encryptionAlgorithm); File gcp = (File) context.getServletContext().getAttribute(BaseModule.GROOVY_CLASS_PATH); FileWriter fw = new FileWriter(new File(gcp, "Security.groovy")); secTemplate.make(bindings).writeTo(fw); IOUtils.closeQuietly(fw); } catch (Exception e) { logger.warn("Couldn't configure users", e); SessionMessages.addWarningMessage(ElementsThreadLocals.getText("couldnt.set.up.user.management._", e)); } } private boolean isMultipleRoles(Table fromTable, Reference ref, Collection<Reference> references) { boolean multipleRoles = false; for (Reference ref2 : references) { if (ref2 != ref && ref2.getActualFromColumn().getTable().equals(fromTable)) { multipleRoles = true; break; } } return multipleRoles; } protected Page createCrudPage(File dir, Table table, List<ChildPage> childPages, Template template) throws Exception { String query = "from " + table.getActualEntityName() + " order by id desc"; String title = Util.guessToWords(table.getActualEntityName()); // hongliangpan add title = table.getMemo(); HashMap<String, String> bindings = new HashMap<String, String>(); bindings.put("parentName", ""); bindings.put("parentProperty", "nothing"); bindings.put("linkToParentProperty", NO_LINK_TO_PARENT); return createCrudPage(dir, table, query, childPages, template, bindings, title); } protected Page createCrudPage(File dir, Table table, String query, List<ChildPage> childPages, Template template, Map<String, String> bindings, String title) throws Exception { if (dir.exists()) { SessionMessages.addWarningMessage( ElementsThreadLocals.getText("directory.exists.page.not.created._", dir.getAbsolutePath())); return null; } else if (dir.mkdirs()) { logger.info("Creating CRUD page {}", dir.getAbsolutePath()); CrudConfiguration configuration = new CrudConfiguration(); configuration.setDatabase(connectionProvider.getDatabase().getDatabaseName()); configuration.setupDefaults(); configuration.setQuery(query); String variable = table.getActualEntityName(); configuration.setVariable(variable); detectLargeResultSet(table, configuration); configuration.setName(table.getActualEntityName()); configuration.setSearchTitle("Search " + title); configuration.setCreateTitle("Create " + title); configuration.setEditTitle("Edit " + title); configuration.setReadTitle(title); int summ = 0; String linkToParentProperty = bindings.get("linkToParentProperty"); for (Column column : table.getColumns()) { summ = setupColumn(column, configuration, summ, linkToParentProperty); } DispatcherLogic.saveConfiguration(dir, configuration); Page page = new Page(); page.setId(RandomUtil.createRandomId()); page.setTitle(title); page.setDescription(title); Collection<Reference> references = children.get(table); if (references != null && depth < maxDepth) { ArrayList<ChildPage> pages = page.getDetailLayout().getChildPages(); depth++; for (Reference ref : references) { createChildCrudPage(dir, template, variable, references, ref, pages); } depth--; Collections.sort(pages, new Comparator<ChildPage>() { public int compare(ChildPage o1, ChildPage o2) { return o1.getName().compareToIgnoreCase(o2.getName()); } }); } DispatcherLogic.savePage(dir, page); File actionFile = new File(dir, "action.groovy"); FileWriter fileWriter = new FileWriter(actionFile); template.make(bindings).writeTo(fileWriter); IOUtils.closeQuietly(fileWriter); logger.debug("Creating _detail directory"); File detailDir = new File(dir, PageInstance.DETAIL); if (!detailDir.isDirectory() && !detailDir.mkdir()) { logger.warn("Could not create detail directory {}", detailDir.getAbsolutePath()); SessionMessages.addWarningMessage( ElementsThreadLocals.getText("couldnt.create.directory", detailDir.getAbsolutePath())); } ChildPage childPage = new ChildPage(); childPage.setName(dir.getName()); childPage.setShowInNavigation(true); childPages.add(childPage); return page; } else { logger.warn("Couldn't create directory {}", dir.getAbsolutePath()); SessionMessages.addWarningMessage( ElementsThreadLocals.getText("couldnt.create.directory", dir.getAbsolutePath())); return null; } } public static final int MULTILINE_THRESHOLD = 256; protected int setupColumn(Column column, CrudConfiguration configuration, int columnsInSummary, String linkToParentProperty) { if (column.getActualJavaType() == null) { logger.debug("Column without a javaType, skipping: {}", column.getQualifiedName()); return columnsInSummary; } Table table = column.getTable(); @SuppressWarnings({ "StringEquality" }) boolean enabled = !(linkToParentProperty != NO_LINK_TO_PARENT && column.getActualPropertyName().equals(linkToParentProperty)) && !isUnsupportedProperty(column); boolean propertyIsUserPassword = table.getQualifiedName().equals(userTableName) && column.getActualPropertyName().equals(userPasswordProperty); boolean inPk = DatabaseLogic.isInPk(column); boolean inFk = DatabaseLogic.isInFk(column); boolean inSummary = enabled && (inPk || columnsInSummary < maxColumnsInSummary) && !propertyIsUserPassword; boolean updatable = enabled && !column.isAutoincrement() && !inPk; boolean insertable = enabled && !column.isAutoincrement(); // hongliangpan add if (column.getColumnName().startsWith("c_is_")) { column.setJavaType(Boolean.class.getName()); } if (!configuration.isLargeResultSet()) { detectBooleanColumn(table, column); } if (enabled && inPk && !inFk && Number.class.isAssignableFrom(column.getActualJavaType()) && !column.isAutoincrement()) { for (PrimaryKeyColumn pkc : table.getPrimaryKey().getPrimaryKeyColumns()) { if (pkc.getActualColumn().equals(column)) { pkc.setGenerator(new IncrementGenerator(pkc)); insertable = false; break; } } } if (propertyIsUserPassword) { Annotation annotation = DatabaseLogic.findAnnotation(column, Password.class); if (annotation == null) { column.getAnnotations().add(new Annotation(column, Password.class.getName())); } insertable = false; updatable = false; } if (!propertyIsUserPassword && column.getActualJavaType() == String.class && column.getLength() > MULTILINE_THRESHOLD && isNewConnectionProvider()) { Annotation annotation = DatabaseLogic.findAnnotation(column, Multiline.class); if (annotation == null) { annotation = new Annotation(column, Multiline.class.getName()); annotation.getValues().add("true"); column.getAnnotations().add(annotation); } } CrudProperty crudProperty = new CrudProperty(); crudProperty.setEnabled(enabled); crudProperty.setName(column.getActualPropertyName()); // hongliangpan add crudProperty.setLabel(column.getMemo()); crudProperty.setInsertable(insertable); crudProperty.setUpdatable(updatable); if (inSummary) { crudProperty.setInSummary(true); crudProperty.setSearchable(true); columnsInSummary++; } // hongliangpan add ?c_tag1 c_config processTagField(crudProperty, column); processCID(crudProperty, column); configuration.getProperties().add(crudProperty); return columnsInSummary; } // hongliangpan add process ?c_tag1 c_config private void processCID(CrudProperty crudProperty, Column column) { if (!column.getColumnName().equalsIgnoreCase("c_id")) { return; } crudProperty.setEnabled(false); crudProperty.setInsertable(false); crudProperty.setUpdatable(false); crudProperty.setInSummary(false); crudProperty.setSearchable(false); } // hongliangpan add process ?c_tag1 c_config private void processTagField(CrudProperty crudProperty, Column column) { if (!column.getColumnName().startsWith("c_tag") && !column.getColumnName().equalsIgnoreCase("c_config")) { return; } crudProperty.setEnabled(false); crudProperty.setInsertable(false); crudProperty.setUpdatable(false); crudProperty.setInSummary(false); crudProperty.setSearchable(false); } protected boolean isUnsupportedProperty(Column column) { // I blob su db non sono supportati al momento return column.getJdbcType() == Types.BLOB || column.getJdbcType() == Types.LONGVARBINARY; } protected final Set<Column> detectedBooleanColumns = new HashSet<Column>(); protected void detectBooleanColumn(Table table, Column column) { if (detectedBooleanColumns.contains(column)) { return; } if (column.getJdbcType() == Types.INTEGER || column.getJdbcType() == Types.DECIMAL || column.getJdbcType() == Types.NUMERIC) { logger.info("Detecting whether numeric column " + column.getQualifiedName() + " is boolean by examining " + "its values..."); // Detect booleans Connection connection = null; try { connection = connectionProvider.acquireConnection(); liquibase.database.Database implementation = DatabaseFactory.getInstance() .findCorrectDatabaseImplementation(new JdbcConnection(connection)); String sql = "select count(" + implementation.escapeDatabaseObject(column.getColumnName()) + ") " + "from " + implementation.escapeTableName(table.getSchemaName(), table.getTableName()); PreparedStatement statement = connection.prepareStatement(sql); setQueryTimeout(statement, 1); statement.setMaxRows(1); ResultSet rs = statement.executeQuery(); Long count = null; if (rs.next()) { count = safeGetLong(rs, 1); } if (count == null || count < 10) { logger.info("Cannot determine if numeric column {} is boolean, count is {}", column.getQualifiedName(), count); return; } sql = "select distinct(" + implementation.escapeDatabaseObject(column.getColumnName()) + ") " + "from " + implementation.escapeTableName(table.getSchemaName(), table.getTableName()); statement = connection.prepareStatement(sql); setQueryTimeout(statement, 1); statement.setMaxRows(3); rs = statement.executeQuery(); int valueCount = 0; boolean only0and1 = true; while (rs.next()) { valueCount++; if (valueCount > 2) { only0and1 = false; break; } Long value = safeGetLong(rs, 1); only0and1 &= value != null && (value == 0 || value == 1); } if (only0and1 && valueCount == 2) { logger.info("Column appears to be of boolean type."); column.setJavaType(Boolean.class.getName()); } else { logger.info("Column appears not to be of boolean type."); } statement.close(); } catch (Exception e) { logger.debug("Could not determine whether column " + column.getQualifiedName() + " is boolean", e); logger.info("Could not determine whether column " + column.getQualifiedName() + " is boolean"); } finally { try { if (connection != null) { connection.close(); } } catch (SQLException e) { logger.error("Could not close connection", e); } } detectedBooleanColumns.add(column); } } protected final Map<Table, Boolean> largeResultSet = new HashMap<Table, Boolean>(); protected void detectLargeResultSet(Table table, CrudConfiguration configuration) { Boolean lrs = largeResultSet.get(table); if (lrs != null) { configuration.setLargeResultSet(lrs); return; } Connection connection = null; try { logger.info("Trying to detect whether table {} has many records...", table.getQualifiedName()); connection = connectionProvider.acquireConnection(); liquibase.database.Database implementation = DatabaseFactory.getInstance() .findCorrectDatabaseImplementation(new JdbcConnection(connection)); String sql = "select count(*) from " + implementation.escapeTableName(table.getSchemaName(), table.getTableName()); PreparedStatement statement = connection.prepareStatement(sql); setQueryTimeout(statement, 1); statement.setMaxRows(1); ResultSet rs = statement.executeQuery(); if (rs.next()) { Long count = safeGetLong(rs, 1); if (count != null) { if (count > LARGE_RESULT_SET_THRESHOLD) { logger.info("Table " + table.getQualifiedName() + " currently has " + count + " rows, which is bigger than " + "the threshold (" + LARGE_RESULT_SET_THRESHOLD + ") for large result sets. It will be " + "marked as largeResultSet = true and no autodetection based on table data will be " + "attempted, in order to keep the processing time reasonable."); configuration.setLargeResultSet(true); } else { logger.info("Table " + table.getQualifiedName() + " currently has " + count + " rows, which is smaller than " + "the threshold (" + LARGE_RESULT_SET_THRESHOLD + ") for large result sets. It will be " + "analyzed normally."); } } else { logger.warn("Could not determine number of records, assuming large result set"); configuration.setLargeResultSet(true); } } statement.close(); } catch (Exception e) { logger.error("Could not determine count", e); } finally { try { if (connection != null) { connection.close(); } } catch (SQLException e) { logger.error("Could not close connection", e); } } largeResultSet.put(table, configuration.isLargeResultSet()); } protected void setQueryTimeout(PreparedStatement statement, int seconds) { try { statement.setQueryTimeout(seconds); } catch (Exception e) { logger.debug("setQueryTimeout not supported", e); } } public static Long safeGetLong(ResultSet rs, int index) throws SQLException { Object object = rs.getObject(index); if (object instanceof Number) { return ((Number) object).longValue(); } else { return null; } } protected void createChildCrudPage(File dir, Template template, String parentName, Collection<Reference> references, Reference ref, ArrayList<ChildPage> pages) throws Exception { Column fromColumn = ref.getActualFromColumn(); Table fromTable = fromColumn.getTable(); String entityName = fromTable.getActualEntityName(); String parentProperty = ref.getActualToColumn().getActualPropertyName(); String linkToParentProperty = fromColumn.getActualPropertyName(); String childQuery = "from " + entityName + " where " + linkToParentProperty + " = %{#" + parentName + "." + parentProperty + "}" + " order by id desc"; String childDirName = entityName; boolean multipleRoles = isMultipleRoles(fromTable, ref, references); if (multipleRoles) { childDirName += "-as-" + linkToParentProperty; } File childDir = new File(new File(dir, PageInstance.DETAIL), childDirName); String childTitle = Util.guessToWords(childDirName); Map<String, String> bindings = new HashMap<String, String>(); bindings.put("parentName", parentName); bindings.put("parentProperty", parentProperty); bindings.put("linkToParentProperty", linkToParentProperty); createCrudPage(childDir, fromTable, childQuery, pages, template, bindings, childTitle); } public SelectField getConnectionProviderField() { return connectionProviderField; } public Form getJndiCPForm() { return jndiCPForm; } public Form getJdbcCPForm() { return jdbcCPForm; } public ConnectionProvider getConnectionProvider() { return connectionProvider; } public String getConnectionProviderName() { return connectionProviderName; } public void setConnectionProviderName(String connectionProviderName) { this.connectionProviderName = connectionProviderName; } public boolean isJdbc() { return connectionProviderType == null || connectionProviderType.equals(JDBC); } public boolean isJndi() { return StringUtils.equals(connectionProviderType, JNDI); } public String getConnectionProviderType() { return connectionProviderType; } public void setConnectionProviderType(String connectionProviderType) { this.connectionProviderType = connectionProviderType; } public Form getConnectionProviderForm() { return connectionProviderForm; } public TableForm getSchemasForm() { return schemasForm; } public List<SelectableSchema> getSelectableSchemas() { return selectableSchemas; } @LabelI18N("users.table") public String getUserTableName() { return userTableName; } public void setUserTableName(String userTableName) { this.userTableName = userTableName; } @LabelI18N("groups.table") public String getGroupTableName() { return groupTableName; } public void setGroupTableName(String groupTableName) { this.groupTableName = groupTableName; } public Form getUserAndGroupTablesForm() { return userAndGroupTablesForm; } public Form getUserManagementSetupForm() { return userManagementSetupForm; } @LabelI18N("username.property") public String getUserNameProperty() { return userNameProperty; } public void setUserNameProperty(String userNameProperty) { this.userNameProperty = userNameProperty; } @LabelI18N("email.property") public String getUserEmailProperty() { return userEmailProperty; } public void setUserEmailProperty(String userEmailProperty) { this.userEmailProperty = userEmailProperty; } @LabelI18N("token.property") public String getUserTokenProperty() { return userTokenProperty; } public void setUserTokenProperty(String userTokenProperty) { this.userTokenProperty = userTokenProperty; } @LabelI18N("user.id.property") public String getUserIdProperty() { return userIdProperty; } public void setUserIdProperty(String userIdProperty) { this.userIdProperty = userIdProperty; } @LabelI18N("password.property") public String getUserPasswordProperty() { return userPasswordProperty; } public void setUserPasswordProperty(String userPasswordProperty) { this.userPasswordProperty = userPasswordProperty; } public String getGroupIdProperty() { return groupIdProperty; } public void setGroupIdProperty(String groupIdProperty) { this.groupIdProperty = groupIdProperty; } @LabelI18N("user-group.join.table") public String getUserGroupTableName() { return userGroupTableName; } public void setUserGroupTableName(String userGroupTableName) { this.userGroupTableName = userGroupTableName; } public String getGroupNameProperty() { return groupNameProperty; } public void setGroupNameProperty(String groupNameProperty) { this.groupNameProperty = groupNameProperty; } @LabelI18N("property.that.links.to.group") public String getGroupLinkProperty() { return groupLinkProperty; } public void setGroupLinkProperty(String groupLinkProperty) { this.groupLinkProperty = groupLinkProperty; } @LabelI18N("property.that.links.to.user") public String getUserLinkProperty() { return userLinkProperty; } public void setUserLinkProperty(String userLinkProperty) { this.userLinkProperty = userLinkProperty; } @LabelI18N("name.of.the.administrators.group") public String getAdminGroupName() { return adminGroupName; } public void setAdminGroupName(String adminGroupName) { this.adminGroupName = adminGroupName; } @LabelI18N("password.encryption.algorithm") public String getEncryptionAlgorithm() { return encryptionAlgorithm; } public void setEncryptionAlgorithm(String encryptionAlgorithm) { this.encryptionAlgorithm = encryptionAlgorithm; } public String getGenerationStrategy() { return generationStrategy; } public void setGenerationStrategy(String generationStrategy) { this.generationStrategy = generationStrategy; } public boolean isGenerateCalendar() { return generateCalendar; } public void setGenerateCalendar(boolean generateCalendar) { this.generateCalendar = generateCalendar; } public BooleanField getGenerateCalendarField() { return generateCalendarField; } public Persistence getPersistence() { return persistence; } // Wizard implementation public static class Step { public final String number; public final String title; public Step(String number, String title) { this.number = number; this.title = title; } public String getNumber() { return number; } public String getTitle() { return title; } } @Override public Resolution preparePage() { return null; } public List<Step> getSteps() { List<Step> steps = new ArrayList<Step>(); steps.add(new Step("1", ElementsThreadLocals.getText("connect.to.your.database"))); steps.add(new Step("2", ElementsThreadLocals.getText("select.the.database.schemas.to.import"))); steps.add(new Step("3", ElementsThreadLocals.getText("set.up.user.management"))); if (userTable != null) { steps.add(new Step("3a", ElementsThreadLocals.getText("customize.user.management"))); } steps.add(new Step("4", ElementsThreadLocals.getText("generate.pages"))); steps.add(new Step("5", ElementsThreadLocals.getText("build.the.application"))); return steps; } public int getCurrentStepIndex() { return step; } }