Java tutorial
/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.geronimo.console.databasemanager.wizard; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.PrintWriter; import java.io.Serializable; import java.io.StringReader; import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; import java.net.URLClassLoader; import java.net.URLDecoder; import java.net.URLEncoder; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.Driver; import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Random; import java.util.Set; import java.util.SortedSet; import javax.enterprise.deploy.model.DDBean; import javax.enterprise.deploy.model.DDBeanRoot; import javax.enterprise.deploy.shared.ModuleType; import javax.enterprise.deploy.spi.DeploymentConfiguration; import javax.enterprise.deploy.spi.DeploymentManager; import javax.enterprise.deploy.spi.Target; import javax.enterprise.deploy.spi.TargetModuleID; import javax.enterprise.deploy.spi.status.ProgressObject; import javax.portlet.ActionRequest; import javax.portlet.ActionResponse; import javax.portlet.PortletConfig; import javax.portlet.PortletException; import javax.portlet.PortletRequest; import javax.portlet.PortletRequestDispatcher; import javax.portlet.PortletSession; import javax.portlet.RenderRequest; import javax.portlet.RenderResponse; import javax.portlet.WindowState; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.portlet.PortletFileUpload; import org.apache.geronimo.connector.deployment.jsr88.ConfigPropertySetting; import org.apache.geronimo.connector.deployment.jsr88.ConnectionDefinition; import org.apache.geronimo.connector.deployment.jsr88.ConnectionDefinitionInstance; import org.apache.geronimo.connector.deployment.jsr88.ConnectionManager; import org.apache.geronimo.connector.deployment.jsr88.Connector15DCBRoot; import org.apache.geronimo.connector.deployment.jsr88.ConnectorDCB; import org.apache.geronimo.connector.deployment.jsr88.ResourceAdapter; import org.apache.geronimo.connector.deployment.jsr88.SinglePool; import org.apache.geronimo.connector.outbound.PoolingAttributes; import org.apache.geronimo.console.BasePortlet; import org.apache.geronimo.console.ajax.ProgressInfo; import org.apache.geronimo.console.databasemanager.ManagementHelper; import org.apache.geronimo.console.util.PortletManager; import org.apache.geronimo.converter.DatabaseConversionStatus; import org.apache.geronimo.converter.JDBCPool; import org.apache.geronimo.converter.bea.WebLogic81DatabaseConverter; import org.apache.geronimo.converter.jboss.JBoss4DatabaseConverter; import org.apache.geronimo.deployment.service.jsr88.EnvironmentData; import org.apache.geronimo.deployment.tools.loader.ConnectorDeployable; import org.apache.geronimo.gbean.AbstractName; import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory; import org.apache.geronimo.kernel.GBeanNotFoundException; import org.apache.geronimo.kernel.InternalKernelException; import org.apache.geronimo.kernel.KernelRegistry; import org.apache.geronimo.kernel.config.ConfigurationManager; import org.apache.geronimo.kernel.config.ConfigurationUtil; import org.apache.geronimo.kernel.management.State; import org.apache.geronimo.kernel.proxy.GeronimoManagedBean; import org.apache.geronimo.kernel.repository.Artifact; import org.apache.geronimo.kernel.repository.FileWriteMonitor; import org.apache.geronimo.kernel.repository.ListableRepository; import org.apache.geronimo.kernel.repository.WriteableRepository; import org.apache.geronimo.kernel.util.XmlUtil; import org.apache.geronimo.kernel.Jsr77Naming; import org.apache.geronimo.management.geronimo.JCAManagedConnectionFactory; import org.apache.geronimo.management.geronimo.ResourceAdapterModule; import org.apache.geronimo.system.plugin.PluginInstallerGBean; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; /** * A portlet that lets you configure and deploy JDBC connection pools. * * @version $Rev: 1245881 $ $Date: 2012-02-18 15:39:05 +0800 (Sat, 18 Feb 2012) $ */ public class DatabasePoolPortlet extends BasePortlet { private static final Logger log = LoggerFactory.getLogger(DatabasePoolPortlet.class); private final static Set<String> INCLUDE_ARTIFACTIDS = new HashSet<String>(Arrays.asList("system-database")); private final static Set<String> EXCLUDE_GROUPIDS = new HashSet<String>(Arrays.asList( "org.apache.geronimo.modules", "org.apache.geronimo.configs", "org.apache.geronimo.applications", "org.apache.geronimo.assemblies", "org.apache.cxf", "org.apache.tomcat", "org.tranql", "commons-cli", "commons-io", "commons-logging", "commons-lang", "axis", "org.apache.axis2", "org.apache.directory", "org.apache.activemq", "org.apache.openejb", "org.apache.myfaces", "org.mortbay.jetty")); private final static String DRIVER_SESSION_KEY = "org.apache.geronimo.console.dbpool.Drivers"; private final static String CONFIG_SESSION_KEY = "org.apache.geronimo.console.dbpool.ConfigParam"; private final static String DRIVER_INFO_URL = "http://geronimo.apache.org/driver-downloads.properties"; private static final String LIST_VIEW = "/WEB-INF/view/dbwizard/list.jsp"; private static final String EDIT_VIEW = "/WEB-INF/view/dbwizard/edit.jsp"; private static final String SELECT_RDBMS_VIEW = "/WEB-INF/view/dbwizard/selectDatabase.jsp"; private static final String BASIC_PARAMS_VIEW = "/WEB-INF/view/dbwizard/basicParams.jsp"; private static final String CONFIRM_URL_VIEW = "/WEB-INF/view/dbwizard/confirmURL.jsp"; private static final String TEST_CONNECTION_VIEW = "/WEB-INF/view/dbwizard/testConnection.jsp"; private static final String DOWNLOAD_VIEW = "/WEB-INF/view/dbwizard/selectDownload.jsp"; private static final String DOWNLOAD_STATUS_VIEW = "/WEB-INF/view/dbwizard/downloadStatus.jsp"; private static final String SHOW_PLAN_VIEW = "/WEB-INF/view/dbwizard/showPlan.jsp"; private static final String IMPORT_UPLOAD_VIEW = "/WEB-INF/view/dbwizard/importUpload.jsp"; private static final String IMPORT_STATUS_VIEW = "/WEB-INF/view/dbwizard/importStatus.jsp"; private static final String USAGE_VIEW = "/WEB-INF/view/dbwizard/usage.jsp"; private static final String LIST_MODE = "list"; private static final String EDIT_MODE = "edit"; private static final String SELECT_RDBMS_MODE = "rdbms"; private static final String BASIC_PARAMS_MODE = "params"; private static final String CONFIRM_URL_MODE = "url"; private static final String TEST_CONNECTION_MODE = "test"; private static final String SHOW_PLAN_MODE = "plan"; private static final String DOWNLOAD_MODE = "download"; private static final String DOWNLOAD_STATUS_MODE = "downloadStatus"; private static final String EDIT_EXISTING_MODE = "editExisting"; private static final String DELETE_MODE = "delete"; private static final String SAVE_MODE = "save"; private static final String IMPORT_START_MODE = "startImport"; private static final String IMPORT_UPLOAD_MODE = "importUpload"; private static final String IMPORT_STATUS_MODE = "importStatus"; private static final String IMPORT_COMPLETE_MODE = "importComplete"; private static final String WEBLOGIC_IMPORT_MODE = "weblogicImport"; private static final String USAGE_MODE = "usage"; private static final String IMPORT_EDIT_MODE = "importEdit"; private static final String MODE_KEY = "mode"; private static final String LOCAL = "LOCAL"; private static final String XA = "XA"; private static final String NONE = "NONE"; private static final String[] ORDERED_PROPERTY_NAMES = { "property-DatabaseName", "property-CreateDatabase", "property-UserName", "property-Password" }; private PortletRequestDispatcher listView; private PortletRequestDispatcher editView; private PortletRequestDispatcher selectRDBMSView; private PortletRequestDispatcher basicParamsView; private PortletRequestDispatcher confirmURLView; private PortletRequestDispatcher testConnectionView; private PortletRequestDispatcher downloadView; private PortletRequestDispatcher downloadStatusView; private PortletRequestDispatcher planView; private PortletRequestDispatcher importUploadView; private PortletRequestDispatcher importStatusView; private PortletRequestDispatcher usageView; private Map<String, String> rarPathMap; public void init(PortletConfig portletConfig) throws PortletException { super.init(portletConfig); listView = portletConfig.getPortletContext().getRequestDispatcher(LIST_VIEW); editView = portletConfig.getPortletContext().getRequestDispatcher(EDIT_VIEW); selectRDBMSView = portletConfig.getPortletContext().getRequestDispatcher(SELECT_RDBMS_VIEW); basicParamsView = portletConfig.getPortletContext().getRequestDispatcher(BASIC_PARAMS_VIEW); confirmURLView = portletConfig.getPortletContext().getRequestDispatcher(CONFIRM_URL_VIEW); testConnectionView = portletConfig.getPortletContext().getRequestDispatcher(TEST_CONNECTION_VIEW); downloadView = portletConfig.getPortletContext().getRequestDispatcher(DOWNLOAD_VIEW); downloadStatusView = portletConfig.getPortletContext().getRequestDispatcher(DOWNLOAD_STATUS_VIEW); planView = portletConfig.getPortletContext().getRequestDispatcher(SHOW_PLAN_VIEW); importUploadView = portletConfig.getPortletContext().getRequestDispatcher(IMPORT_UPLOAD_VIEW); importStatusView = portletConfig.getPortletContext().getRequestDispatcher(IMPORT_STATUS_VIEW); usageView = portletConfig.getPortletContext().getRequestDispatcher(USAGE_VIEW); rarPathMap = new HashMap<String, String>(); rarPathMap.put("TranQL XA Resource Adapter for DB2", "tranql-connector-db2-xa"); rarPathMap.put("TranQL XA Resource Adapter for DB2ISeries", "tranql-connector-db2ISeries-xa"); rarPathMap.put("TranQL Client Local Transaction Resource Adapter for Apache Derby", "tranql-connector-derby-client-local"); rarPathMap.put("TranQL Client XA Resource Adapter for Apache Derby", "tranql-connector-derby-client-xa"); rarPathMap.put("TranQL Embedded Local Transaction Resource Adapter for Apache Derby", "tranql-connector-derby-embed-local"); rarPathMap.put("TranQL Embedded XA Resource Adapter for Apache Derby", "tranql-connector-derby-embed-xa"); // rarPathMap.put("TranQL Embedded XA Resource Adapter for Apache Derby", "tranql-connector-derby-embed-local"); rarPathMap.put("TranQL XA Resource Adapter for Informix", "tranql-connector-informix-xa"); rarPathMap.put("TranQL Client Local Transaction Resource Adapter for MySQL", "tranql-connector-mysql-local"); rarPathMap.put("TranQL Client XA Resource Adapter for MySQL", "tranql-connector-mysql-xa"); rarPathMap.put("TranQL Local Resource Adapter for Oracle", "tranql-connector-oracle-local"); rarPathMap.put("TranQL XA Resource Adapter for Oracle", "tranql-connector-oracle-xa"); rarPathMap.put("TranQL Local Resource Adapter for PostgreSQL", "tranql-connector-postgresql-local"); rarPathMap.put("TranQL XA Resource Adapter for PostgreSQL", "tranql-connector-postgresql-xa"); rarPathMap.put("TranQL XA Resource Adapter for SQLServer 2000", "tranql-connector-sqlserver2000-xa"); rarPathMap.put("TranQL XA Resource Adapter for SQLServer 2005", "tranql-connector-sqlserver2005-xa"); rarPathMap.put("TranQL XA Resource Adapter for SQLServer 2008", "tranql-connector-sqlserver2008-xa"); } public void destroy() { listView = null; editView = null; selectRDBMSView = null; basicParamsView = null; confirmURLView = null; testConnectionView = null; downloadView = null; downloadStatusView = null; planView = null; importUploadView = null; importStatusView = null; usageView = null; rarPathMap.clear(); super.destroy(); } public DriverDownloader.DriverInfo[] getDriverInfo(PortletRequest request) { PortletSession session = request.getPortletSession(true); DriverDownloader.DriverInfo[] results = (DriverDownloader.DriverInfo[]) session .getAttribute(DRIVER_SESSION_KEY, PortletSession.APPLICATION_SCOPE); if (results == null || results.length == 0) { DriverDownloader downloader = new DriverDownloader(); try { results = downloader.loadDriverInfo(new URL(DRIVER_INFO_URL)); session.setAttribute(DRIVER_SESSION_KEY, results, PortletSession.APPLICATION_SCOPE); } catch (MalformedURLException e) { log.error("Unable to download driver data", e); results = new DriverDownloader.DriverInfo[0]; } } return results; } /** * Loads data about a resource adapter. Depending on what we already have, may load * the name and description, but always loads the config property descriptions. * * @param request Pass it or die * @param rarPath If we're creating a new RA, the path to identify it * @param displayName If we're editing an existing RA, its name * @param adapterAbstractName If we're editing an existing RA, its AbstractName * @return resource adapter parameter data object */ public ResourceAdapterParams getRARConfiguration(PortletRequest request, String rarPath, String displayName, String adapterAbstractName) { PortletSession session = request.getPortletSession(true); if (rarPath != null && !rarPath.equals("")) { ResourceAdapterParams results = (ResourceAdapterParams) session .getAttribute(CONFIG_SESSION_KEY + "-" + rarPath, PortletSession.APPLICATION_SCOPE); if (results == null) { results = loadConfigPropertiesByPath(request, rarPath); session.setAttribute(CONFIG_SESSION_KEY + "-" + rarPath, results, PortletSession.APPLICATION_SCOPE); session.setAttribute(CONFIG_SESSION_KEY + "-" + results.displayName, results, PortletSession.APPLICATION_SCOPE); } return results; } else if (displayName != null && !displayName.equals("") && adapterAbstractName != null && !adapterAbstractName.equals("")) { ResourceAdapterParams results = (ResourceAdapterParams) session .getAttribute(CONFIG_SESSION_KEY + "-" + displayName, PortletSession.APPLICATION_SCOPE); if (results == null) { results = loadConfigPropertiesByAbstractName(request, rarPathMap.get(displayName), adapterAbstractName); session.setAttribute(CONFIG_SESSION_KEY + "-" + displayName, results, PortletSession.APPLICATION_SCOPE); } return results; } else { throw new IllegalArgumentException(); } } public void processAction(ActionRequest actionRequest, ActionResponse actionResponse) throws PortletException, IOException { String mode = actionRequest.getParameter(MODE_KEY); if (mode.equals(IMPORT_UPLOAD_MODE)) { processImportUpload(actionRequest, actionResponse); actionResponse.setRenderParameter(MODE_KEY, IMPORT_STATUS_MODE); return; } PoolData data = new PoolData(); data.load(actionRequest); if (mode.equals("process-" + SELECT_RDBMS_MODE)) { DatabaseDriver info = getDatabaseInfo(actionRequest, data); if (info != null) { data.rarPath = info.getRAR().toString(); if (info.isSpecific()) { data.adapterDisplayName = "Unknown"; // will pick these up when we process the RA type in the render request data.adapterDescription = "Unknown"; actionResponse.setRenderParameter(MODE_KEY, EDIT_MODE); } else { data.driverClass = info.getDriverClassName(); data.urlPrototype = info.getURLPrototype(); actionResponse.setRenderParameter(MODE_KEY, BASIC_PARAMS_MODE); } } else { actionResponse.setRenderParameter(MODE_KEY, SELECT_RDBMS_MODE); } } else if (mode.equals("process-" + DOWNLOAD_MODE)) { String name = actionRequest.getParameter("driverName"); DriverDownloader.DriverInfo[] drivers = getDriverInfo(actionRequest); DriverDownloader.DriverInfo found = null; for (DriverDownloader.DriverInfo driver : drivers) { if (driver.getName().equals(name)) { found = driver; break; } } if (found != null) { data.jars = new String[] { found.getRepositoryURI() }; try { PluginInstallerGBean installer = KernelRegistry.getSingleKernel() .getGBean(PluginInstallerGBean.class); //WriteableRepository repo = PortletManager.getCurrentServer(actionRequest).getWritableRepositories()[0]; final PortletSession session = actionRequest.getPortletSession(); ProgressInfo progressInfo = new ProgressInfo(); progressInfo.setMainMessage("Downloading " + found.getName()); session.setAttribute(ProgressInfo.PROGRESS_INFO_KEY, progressInfo, PortletSession.APPLICATION_SCOPE); // Start the download monitoring new Thread(new Downloader(found, progressInfo, installer)).start(); actionResponse.setRenderParameter(MODE_KEY, DOWNLOAD_STATUS_MODE); } catch (GBeanNotFoundException e) { throw new PortletException(e); } catch (InternalKernelException e) { throw new PortletException(e); } catch (IllegalStateException e) { throw new PortletException(e); } } else { actionResponse.setRenderParameter(MODE_KEY, DOWNLOAD_MODE); } } else if (mode.equals("process-" + DOWNLOAD_STATUS_MODE)) { if (data.getDbtype() == null || data.getDbtype().equals("Other")) { actionResponse.setRenderParameter(MODE_KEY, BASIC_PARAMS_MODE); } else { actionResponse.setRenderParameter(MODE_KEY, EDIT_MODE); } } else if (mode.equals("process-" + BASIC_PARAMS_MODE)) { DatabaseDriver info; info = getDatabaseInfo(actionRequest, data); if (info != null) { data.url = populateURL(info.getURLPrototype(), info.getURLParameters(), data.getUrlProperties()); } if (attemptDriverLoad(actionRequest, data) != null) { actionResponse.setRenderParameter(MODE_KEY, CONFIRM_URL_MODE); } else { actionResponse.setRenderParameter("driverError", "Unable to load driver " + data.driverClass); actionResponse.setRenderParameter(MODE_KEY, BASIC_PARAMS_MODE); } } else if (mode.equals("process-" + CONFIRM_URL_MODE)) { String test = actionRequest.getParameter("test"); if (test == null || test.equals("true")) { try { String targetDBInfo = attemptConnect(actionRequest, data); actionResponse.setRenderParameter("targetDBInfo", targetDBInfo); actionResponse.setRenderParameter("connected", "true"); } catch (Exception e) { StringWriter writer = new StringWriter(); PrintWriter temp = new PrintWriter(writer); e.printStackTrace(temp); temp.flush(); temp.close(); addErrorMessage(actionRequest, getLocalizedString(actionRequest, "dbwizard.testConnection.connectionError"), writer.getBuffer().toString()); actionResponse.setRenderParameter("connected", "false"); } actionResponse.setRenderParameter(MODE_KEY, TEST_CONNECTION_MODE); } else { save(actionRequest, actionResponse, data, false); } } else if (mode.equals(SAVE_MODE)) { save(actionRequest, actionResponse, data, false); } else if (mode.equals(SHOW_PLAN_MODE)) { String plan = save(actionRequest, actionResponse, data, true); actionRequest.getPortletSession(true).setAttribute("deploymentPlan", plan); actionResponse.setRenderParameter(MODE_KEY, SHOW_PLAN_MODE); } else if (mode.equals(EDIT_EXISTING_MODE)) { final String name = actionRequest.getParameter("adapterAbstractName"); loadConnectionFactory(actionRequest, name, data.getAbstractName(), data); actionResponse.setRenderParameter("adapterAbstractName", name); actionResponse.setRenderParameter(MODE_KEY, EDIT_MODE); } else if (mode.equals(SELECT_RDBMS_MODE)) { if (data.getAdapterDisplayName() == null) { // Set a default for a new pool data.adapterDisplayName = "TranQL Generic JDBC Resource Adapter"; } actionResponse.setRenderParameter(MODE_KEY, mode); } else if (mode.equals(WEBLOGIC_IMPORT_MODE)) { String domainDir = actionRequest.getParameter("weblogicDomainDir"); String libDir = actionRequest.getParameter("weblogicLibDir"); try { DatabaseConversionStatus status = WebLogic81DatabaseConverter.convert(libDir, domainDir); actionRequest.getPortletSession(true).setAttribute("ImportStatus", new ImportStatus(status)); actionResponse.setRenderParameter(MODE_KEY, IMPORT_STATUS_MODE); } catch (Exception e) { log.error("Unable to import", e); actionResponse.setRenderParameter("from", actionRequest.getParameter("from")); actionResponse.setRenderParameter(MODE_KEY, IMPORT_START_MODE); } } else if (mode.equals(IMPORT_START_MODE)) { actionResponse.setRenderParameter("from", actionRequest.getParameter("from")); actionResponse.setRenderParameter(MODE_KEY, mode); } else if (mode.equals(IMPORT_EDIT_MODE)) { ImportStatus status = getImportStatus(actionRequest); int index = Integer.parseInt(actionRequest.getParameter("importIndex")); status.setCurrentPoolIndex(index); loadImportedData(actionRequest, data, status.getCurrentPool()); actionResponse.setRenderParameter(MODE_KEY, EDIT_MODE); } else if (mode.equals(IMPORT_COMPLETE_MODE)) { ImportStatus status = getImportStatus(actionRequest); log.warn("Import Results:"); //todo: create a screen for this log.warn(" " + status.getSkippedCount() + " ignored"); log.warn(" " + status.getStartedCount() + " reviewed but not deployed"); log.warn(" " + status.getPendingCount() + " not reviewed"); log.warn(" " + status.getFinishedCount() + " deployed"); actionRequest.getPortletSession().removeAttribute("ImportStatus"); } else if (mode.equals(DELETE_MODE)) { String name = actionRequest.getParameter("adapterAbstractName"); loadConnectionFactory(actionRequest, name, data.getAbstractName(), data); delete(actionRequest, actionResponse, data); } else { actionResponse.setRenderParameter(MODE_KEY, mode); } data.store(actionResponse); } private static class Downloader implements Runnable { private PluginInstallerGBean installer; private DriverDownloader.DriverInfo driver; private ProgressInfo progressInfo; public Downloader(DriverDownloader.DriverInfo driver, ProgressInfo progressInfo, PluginInstallerGBean installer) { this.driver = driver; this.progressInfo = progressInfo; this.installer = installer; } public void run() { DriverDownloader downloader = new DriverDownloader(); try { downloader.loadDriver(installer, driver, new FileWriteMonitor() { private int fileSize; public void writeStarted(String fileDescription, int fileSize) { this.fileSize = fileSize; log.info("Downloading " + fileDescription); } public void writeProgress(int bytes) { int kbDownloaded = (int) Math.floor(bytes / 1024); if (fileSize > 0) { int percent = (bytes * 100) / fileSize; progressInfo.setProgressPercent(percent); progressInfo.setSubMessage(kbDownloaded + " / " + fileSize / 1024 + " Kb downloaded"); } else { progressInfo.setSubMessage(kbDownloaded + " Kb downloaded"); } } public void writeComplete(int bytes) { log.info("Finished downloading " + bytes + " b"); } }); } catch (IOException e) { log.error("Unable to download database driver", e); } finally { progressInfo.setFinished(true); } } } private void loadImportedData(PortletRequest request, PoolData data, ImportStatus.PoolProgress progress) throws PortletException { if (!progress.getType().equals(ImportStatus.PoolProgress.TYPE_XA)) { JDBCPool pool = (JDBCPool) progress.getPool(); data.dbtype = "Other"; data.adapterDisplayName = "TranQL Generic JDBC Resource Adapter"; data.blockingTimeout = getImportString(pool.getBlockingTimeoutMillis()); data.driverClass = pool.getDriverClass(); data.idleTimeout = pool.getIdleTimeoutMillis() != null ? Integer.toString(pool.getIdleTimeoutMillis().intValue() / (60 * 1000)) : null; data.maxSize = getImportString(pool.getMaxSize()); data.minSize = getImportString(pool.getMinSize()); data.name = pool.getName(); data.password = pool.getPassword(); data.url = pool.getJdbcURL(); data.user = pool.getUsername(); if (pool.getDriverClass() != null) { DatabaseDriver info = getDatabaseInfoFromDriver(request, data); if (info != null) { data.rarPath = info.getRAR().toString(); data.urlPrototype = info.getURLPrototype(); } else { throw new PortletException("Don't recognize database driver " + data.driverClass + "!"); } } } else { //todo: handle XA } } private static String getImportString(Integer value) { return value == null ? null : value.toString(); } private boolean processImportUpload(ActionRequest request, ActionResponse response) throws PortletException { String type = request.getParameter("importSource"); response.setRenderParameter("importSource", type); if (!PortletFileUpload.isMultipartContent(request)) { throw new PortletException("Expected file upload"); } PortletFileUpload uploader = new PortletFileUpload(new DiskFileItemFactory()); try { List<FileItem> items = uploader.parseRequest(request); for (FileItem item : items) { if (!item.isFormField()) { File file = File.createTempFile("geronimo-import", ""); file.deleteOnExit(); log.debug("Writing database pool import file to " + file.getAbsolutePath()); item.write(file); DatabaseConversionStatus status = processImport(file, type); request.getPortletSession(true).setAttribute("ImportStatus", new ImportStatus(status)); return true; } else { throw new PortletException("Not expecting any form fields"); } } } catch (PortletException e) { throw e; } catch (Exception e) { throw new PortletException(e); } return false; } private DatabaseConversionStatus processImport(File importFile, String type) throws PortletException, IOException { if (type.equals("JBoss 4")) { return JBoss4DatabaseConverter.convert(new FileReader(importFile)); } else if (type.equals("WebLogic 8.1")) { return WebLogic81DatabaseConverter.convert(new FileReader(importFile)); } else { throw new PortletException("Unknown import type '" + type + "'"); } } private ResourceAdapterParams loadConfigPropertiesByPath(PortletRequest request, String rarPath) { DeploymentManager mgr = ManagementHelper.getManagementHelper(request).getDeploymentManager(); try { //URI uri = getRAR(request, rarPath).toURI(); ConnectorDeployable deployable = new ConnectorDeployable( PortletManager.getRepositoryEntryBundle(request, rarPath)); final DDBeanRoot ddBeanRoot = deployable.getDDBeanRoot(); String adapterName = null, adapterDesc = null; String[] test = ddBeanRoot.getText("connector/display-name"); if (test != null && test.length > 0) { adapterName = test[0]; } test = ddBeanRoot.getText("connector/description"); if (test != null && test.length > 0) { adapterDesc = test[0]; } DDBean[] definitions = ddBeanRoot .getChildBean("connector/resourceadapter/outbound-resourceadapter/connection-definition"); List<ConfigParam> configs = new ArrayList<ConfigParam>(); if (definitions != null) { for (DDBean definition : definitions) { String iface = definition.getText("connectionfactory-interface")[0]; if (iface.equals("javax.sql.DataSource")) { DDBean[] beans = definition.getChildBean("config-property"); for (DDBean bean : beans) { String name = bean.getText("config-property-name")[0].trim(); String type = bean.getText("config-property-type")[0].trim(); test = bean.getText("config-property-value"); String value = test == null || test.length == 0 ? null : test[0].trim(); test = bean.getText("description"); String desc = test == null || test.length == 0 ? null : test[0].trim(); configs.add(new ConfigParam(name, type, desc, value)); } } } } return new ResourceAdapterParams(adapterName, adapterDesc, rarPath.substring(11, rarPath.length() - 5), configs.toArray(new ConfigParam[configs.size()])); } catch (Exception e) { log.error("Unable to read configuration properties", e); return null; } finally { if (mgr != null) mgr.release(); } } private ResourceAdapterParams loadConfigPropertiesByAbstractName(PortletRequest request, String rarPath, String abstractName) { ResourceAdapterModule module = (ResourceAdapterModule) PortletManager.getManagedBean(request, new AbstractName(URI.create(abstractName))); String dd = module.getDeploymentDescriptor(); DocumentBuilderFactory factory = XmlUtil.newDocumentBuilderFactory(); factory.setValidating(false); factory.setNamespaceAware(true); try { DocumentBuilder builder = factory.newDocumentBuilder(); final StringReader reader = new StringReader(dd); Document doc = builder.parse(new InputSource(reader)); reader.close(); Element elem = doc.getDocumentElement(); // connector String displayName = getFirstText(elem.getElementsByTagName("display-name")); String description = getFirstText(elem.getElementsByTagName("description")); elem = (Element) elem.getElementsByTagName("resourceadapter").item(0); elem = (Element) elem.getElementsByTagName("outbound-resourceadapter").item(0); NodeList defs = elem.getElementsByTagName("connection-definition"); List<ConfigParam> all = new ArrayList<ConfigParam>(); for (int i = 0; i < defs.getLength(); i++) { final Element def = (Element) defs.item(i); String iface = getFirstText(def.getElementsByTagName("connectionfactory-interface")).trim(); if (iface.equals("javax.sql.DataSource")) { NodeList configs = def.getElementsByTagName("config-property"); for (int j = 0; j < configs.getLength(); j++) { Element config = (Element) configs.item(j); String name = getFirstText(config.getElementsByTagName("config-property-name")).trim(); String type = getFirstText(config.getElementsByTagName("config-property-type")).trim(); String test = getFirstText(config.getElementsByTagName("config-property-value")); String value = test == null ? null : test.trim(); test = getFirstText(config.getElementsByTagName("description")); String desc = test == null ? null : test.trim(); all.add(new ConfigParam(name, type, desc, value)); } } } return new ResourceAdapterParams(displayName, description, rarPath, all.toArray(new ConfigParam[all.size()])); } catch (Exception e) { log.error("Unable to read resource adapter DD", e); return null; } } private String getFirstText(NodeList list) { if (list.getLength() == 0) { return null; } Element first = (Element) list.item(0); StringBuilder buf = new StringBuilder(); NodeList all = first.getChildNodes(); for (int i = 0; i < all.getLength(); i++) { Node node = all.item(i); if (node.getNodeType() == Node.TEXT_NODE) { buf.append(node.getNodeValue()); } } return buf.toString(); } private void loadConnectionFactory(ActionRequest actionRequest, String adapterName, String factoryName, PoolData data) { AbstractName abstractAdapterName = new AbstractName(URI.create(adapterName)); AbstractName abstractFactoryName = new AbstractName(URI.create(factoryName)); ResourceAdapterModule adapter = (ResourceAdapterModule) PortletManager.getManagedBean(actionRequest, abstractAdapterName); JCAManagedConnectionFactory factory = (JCAManagedConnectionFactory) PortletManager .getManagedBean(actionRequest, abstractFactoryName); data.adapterDisplayName = adapter.getDisplayName(); data.adapterDescription = adapter.getDescription(); try { data.name = (String) abstractFactoryName.getName().get("name"); if (data.isGeneric()) { data.url = (String) factory.getConfigProperty("ConnectionURL"); data.driverClass = (String) factory.getConfigProperty("Driver"); data.user = (String) factory.getConfigProperty("UserName"); data.password = (String) factory.getConfigProperty("Password"); } else { ResourceAdapterParams params = getRARConfiguration(actionRequest, data.getRarPath(), data.getAdapterDisplayName(), adapterName); for (int i = 0; i < params.getConfigParams().length; i++) { ConfigParam cp = params.getConfigParams()[i]; Object value = factory.getConfigProperty(cp.getName()); data.properties.put("property-" + cp.getName(), value == null ? null : value.toString()); } data.sort(); } } catch (Exception e) { log.error("Unable to look up connection property", e); } //todo: push the lookup into ManagementHelper /* PoolingAttributes pool = (PoolingAttributes) factory.getConnectionManagerContainer(); data.minSize = Integer.toString(pool.getPartitionMinSize()); data.maxSize = Integer.toString(pool.getPartitionMaxSize()); data.blockingTimeout = Integer.toString(pool.getBlockingTimeoutMilliseconds()); data.idleTimeout = Integer.toString(pool.getIdleTimeoutMinutes()); */ try { Jsr77Naming naming = new Jsr77Naming(); AbstractName connectionManagerName = naming.createChildName(abstractFactoryName, data.getName(), NameFactory.JCA_CONNECTION_MANAGER); PoolingAttributes pool = (PoolingAttributes) PortletManager.getManagedBean(actionRequest, connectionManagerName); data.minSize = Integer.toString(pool.getPartitionMinSize()); data.maxSize = Integer.toString(pool.getPartitionMaxSize()); data.blockingTimeout = Integer.toString(pool.getBlockingTimeoutMilliseconds()); data.idleTimeout = Integer.toString(pool.getIdleTimeoutMinutes()); } catch (Exception e) { log.error("Cannot load pool data", e); } } protected void doView(RenderRequest renderRequest, RenderResponse renderResponse) throws IOException, PortletException { if (WindowState.MINIMIZED.equals(renderRequest.getWindowState())) { return; } try { String mode = renderRequest.getParameter(MODE_KEY); PoolData data = new PoolData(); data.load(renderRequest); renderRequest.setAttribute("pool", data); // If not headed anywhere in particular, send to list if (mode == null || mode.equals("")) { mode = LIST_MODE; } // If headed to list but there's an import in progress, redirect to import status if (mode.equals(LIST_MODE) && getImportStatus(renderRequest) != null) { mode = IMPORT_STATUS_MODE; } if (mode.equals(LIST_MODE)) { renderList(renderRequest, renderResponse); } else if (mode.equals(EDIT_MODE)) { renderEdit(renderRequest, renderResponse, data); } else if (mode.equals(SELECT_RDBMS_MODE)) { renderSelectRDBMS(renderRequest, renderResponse); } else if (mode.equals(DOWNLOAD_MODE)) { renderDownload(renderRequest, renderResponse); } else if (mode.equals(DOWNLOAD_STATUS_MODE)) { renderDownloadStatus(renderRequest, renderResponse); } else if (mode.equals(BASIC_PARAMS_MODE)) { renderBasicParams(renderRequest, renderResponse, data); } else if (mode.equals(CONFIRM_URL_MODE)) { renderConfirmURL(renderRequest, renderResponse); } else if (mode.equals(TEST_CONNECTION_MODE)) { renderTestConnection(renderRequest, renderResponse); } else if (mode.equals(SHOW_PLAN_MODE)) { renderPlan(renderRequest, renderResponse, data); } else if (mode.equals(IMPORT_START_MODE)) { renderImportUploadForm(renderRequest, renderResponse); } else if (mode.equals(IMPORT_STATUS_MODE)) { renderImportStatus(renderRequest, renderResponse); } else if (mode.equals(USAGE_MODE)) { renderUsage(renderRequest, renderResponse); } } catch (Throwable e) { log.error("Unable to render portlet", e); } } private void renderUsage(RenderRequest request, RenderResponse response) throws IOException, PortletException { usageView.include(request, response); } private void renderImportStatus(RenderRequest request, RenderResponse response) throws IOException, PortletException { request.setAttribute("status", getImportStatus(request)); populatePoolList(request); importStatusView.include(request, response); } private void renderImportUploadForm(RenderRequest request, RenderResponse response) throws IOException, PortletException { request.setAttribute("from", request.getParameter("from")); importUploadView.include(request, response); } private void renderList(RenderRequest renderRequest, RenderResponse renderResponse) throws IOException, PortletException { populatePoolList(renderRequest); listView.include(renderRequest, renderResponse); } private void populatePoolList(PortletRequest renderRequest) { ResourceAdapterModule[] modules = PortletManager.getOutboundRAModules(renderRequest, "javax.sql.DataSource"); List<ConnectionPool> list = new ArrayList<ConnectionPool>(); for (ResourceAdapterModule module : modules) { AbstractName moduleName = PortletManager.getManagementHelper(renderRequest).getNameFor(module); JCAManagedConnectionFactory[] databases = PortletManager.getOutboundFactoriesForRA(renderRequest, module, "javax.sql.DataSource"); for (JCAManagedConnectionFactory db : databases) { AbstractName dbName = PortletManager.getManagementHelper(renderRequest).getNameFor(db); list.add( new ConnectionPool(moduleName, dbName, (String) dbName.getName().get(NameFactory.J2EE_NAME), PortletManager.getManagedBean(renderRequest, dbName).getState())); } } Collections.sort(list); renderRequest.setAttribute("pools", list); } private void renderEdit(RenderRequest renderRequest, RenderResponse renderResponse, PoolData data) throws IOException, PortletException { if (data.abstractName == null || data.abstractName.equals("")) { DatabaseDriver info = getDatabaseInfo(renderRequest, data); loadDriverJARList(renderRequest, info); } if (!data.isGeneric()) { ResourceAdapterParams params = getRARConfiguration(renderRequest, data.getRarPath(), data.getAdapterDisplayName(), renderRequest.getParameter("adapterAbstractName")); data.adapterDisplayName = params.getDisplayName(); data.adapterDescription = params.getDescription(); data.adapterRarPath = params.getRarPath(); Map<String, ConfigParam> map = new HashMap<String, ConfigParam>(); boolean more = false; for (int i = 0; i < params.getConfigParams().length; i++) { ConfigParam param = params.getConfigParams()[i]; if (!data.properties.containsKey("property-" + param.getName())) { data.properties.put("property-" + param.getName(), param.getDefaultValue()); more = true; } map.put("property-" + param.getName(), param); } if (more) { data.loadPropertyNames(); } data.sort(); renderRequest.setAttribute("ConfigParams", map); } editView.include(renderRequest, renderResponse); } private void renderSelectRDBMS(RenderRequest renderRequest, RenderResponse renderResponse) throws IOException, PortletException { renderRequest.setAttribute("databases", getAllDrivers(renderRequest)); selectRDBMSView.include(renderRequest, renderResponse); } private void renderDownload(RenderRequest renderRequest, RenderResponse renderResponse) throws IOException, PortletException { renderRequest.setAttribute("drivers", getDriverInfo(renderRequest)); downloadView.include(renderRequest, renderResponse); } private void renderDownloadStatus(RenderRequest renderRequest, RenderResponse renderResponse) throws IOException, PortletException { downloadStatusView.include(renderRequest, renderResponse); } private void renderBasicParams(RenderRequest renderRequest, RenderResponse renderResponse, PoolData data) throws IOException, PortletException { DatabaseDriver info = getDatabaseInfo(renderRequest, data); loadDriverJARList(renderRequest, info); // Make sure all properties available for the DB are listed if (info != null) { for (String param : info.getURLParameters()) { final String key = "urlproperty-" + param; if (!data.getUrlProperties().containsKey(key)) { data.getUrlProperties().put(key, param.equalsIgnoreCase("port") && info.getDefaultPort() > 0 ? info.getDefaultPort() : null); } } } // Pass on errors renderRequest.setAttribute("driverError", renderRequest.getParameter("driverError")); basicParamsView.include(renderRequest, renderResponse); } private void loadDriverJARList(RenderRequest renderRequest, DatabaseDriver info) { // List the available JARs List<String> list = new ArrayList<String>(); ListableRepository[] repos = PortletManager.getCurrentServer(renderRequest).getRepositories(); Set<Artifact> dependencyFilters = info == null ? null : info.getDependencyFilters(); for (ListableRepository repo : repos) { SortedSet<Artifact> artifacts = repo.list(); for (Artifact artifact : artifacts) { if (dependencyFilters != null) { for (Artifact filter : dependencyFilters) { // It is too strict if using artifact.matches(filter) if (filter.getGroupId() != null && artifact.getGroupId().indexOf(filter.getGroupId()) == -1) continue; if (filter.getArtifactId() != null && artifact.getArtifactId().indexOf(filter.getArtifactId()) == -1) continue; if (filter.getVersion() != null && !artifact.getVersion().equals(filter.getVersion())) continue; if (filter.getType() != null && !artifact.getType().equals(filter.getType())) continue; list.add(artifact.toString()); } } else if (INCLUDE_ARTIFACTIDS.contains(artifact.getArtifactId()) || !EXCLUDE_GROUPIDS.contains(artifact.getGroupId())) { list.add(artifact.toString()); } } } Collections.sort(list); renderRequest.setAttribute("availableJars", list); } private void renderConfirmURL(RenderRequest renderRequest, RenderResponse renderResponse) throws IOException, PortletException { confirmURLView.include(renderRequest, renderResponse); } private void renderTestConnection(RenderRequest renderRequest, RenderResponse renderResponse) throws IOException, PortletException { // Pass on results renderRequest.setAttribute("targetDBInfo", renderRequest.getParameter("targetDBInfo")); renderRequest.setAttribute("connected", Boolean.valueOf(renderRequest.getParameter("connected"))); testConnectionView.include(renderRequest, renderResponse); } private void renderPlan(RenderRequest renderRequest, RenderResponse renderResponse, PoolData data) throws IOException, PortletException { // Pass on results renderRequest.setAttribute("deploymentPlan", renderRequest.getPortletSession().getAttribute("deploymentPlan")); // Digest the RAR URI String path = PortletManager.getRepositoryEntry(renderRequest, data.getRarPath()).getPath(); String base = PortletManager.getCurrentServer(renderRequest).getServerInfo().getCurrentBaseDirectory(); if (base != null && path.startsWith(base)) { path = path.substring(base.length()); if (path.startsWith("/")) { path = path.substring(1); } } else { int pos = path.lastIndexOf('/'); path = path.substring(pos + 1); } renderRequest.setAttribute("rarRelativePath", path); planView.include(renderRequest, renderResponse); } private static String attemptConnect(PortletRequest request, PoolData data) throws SQLException, IllegalAccessException, InstantiationException { Class driverClass = attemptDriverLoad(request, data); Driver driver = (Driver) driverClass.newInstance(); if (driver.acceptsURL(data.url)) { Properties props = new Properties(); if (data.user != null) { props.put("user", data.user); } if (data.password != null) { props.put("password", data.password); } Connection con = null; try { con = driver.connect(data.url, props); final DatabaseMetaData metaData = con.getMetaData(); return metaData.getDatabaseProductName() + " " + metaData.getDatabaseProductVersion(); } finally { if (con != null) { try { con.close(); } catch (SQLException e) { //ignore } } } } else throw new SQLException("Driver " + data.getDriverClass() + " does not accept URL " + data.url); } private void delete(PortletRequest request, ActionResponse response, PoolData data) { // check to make sure the abstract name does not begin with 'org.apache.geronimo.configs' // if it does not - then delete it -- otherwise it is a system database if (data.getAbstractName() != null) { boolean isSystemDatabasePool = (data.getAbstractName().indexOf("org.apache.geronimo.configs") == 0); if (!isSystemDatabasePool) { DeploymentManager mgr = ManagementHelper.getManagementHelper(request).getDeploymentManager(); try { // retrieve all running modules TargetModuleID[] runningIds = mgr.getRunningModules(ModuleType.RAR, mgr.getTargets()); // index of module to keep int index = -1; // only keep module id that is associated with selected DB pool for (int i = 0; i < runningIds.length; i++) { if (data.getAbstractName().contains(runningIds[i].getModuleID())) { index = i; break; } } TargetModuleID[] ids = { runningIds[index] }; // undeploy the db pool ProgressObject po = mgr.undeploy(ids); waitForProgress(po); if (po.getDeploymentStatus().isCompleted()) { log.info("Undeployment completed successfully!"); } } catch (Exception e) { log.error("Undeployment unsuccessful!"); } finally { if (mgr != null) mgr.release(); } } } } private static String save(PortletRequest request, ActionResponse response, PoolData data, boolean planOnly) { ImportStatus status = getImportStatus(request); if (data.abstractName == null || data.abstractName.equals("")) { // we're creating a new pool data.name = data.name.replaceAll("\\s", ""); DeploymentManager mgr = ManagementHelper.getManagementHelper(request).getDeploymentManager(); try { String rarPath = data.getRarPath(); File rarFile = getRAR(request, rarPath); //URI uri = getRAR(request, data.getRarPath()).toURI(); ConnectorDeployable deployable = new ConnectorDeployable( PortletManager.getRepositoryEntryBundle(request, rarPath)); DeploymentConfiguration config = mgr.createConfiguration(deployable); final DDBeanRoot ddBeanRoot = deployable.getDDBeanRoot(); Connector15DCBRoot root = (Connector15DCBRoot) config.getDConfigBeanRoot(ddBeanRoot); ConnectorDCB connector = (ConnectorDCB) root .getDConfigBean(ddBeanRoot.getChildBean(root.getXpaths()[0])[0]); EnvironmentData environment = new EnvironmentData(); connector.setEnvironment(environment); org.apache.geronimo.deployment.service.jsr88.Artifact configId = new org.apache.geronimo.deployment.service.jsr88.Artifact(); environment.setConfigId(configId); configId.setGroupId("console.dbpool"); configId.setVersion("1.0"); configId.setType("car"); String artifactId = data.name; // simply replace / with _ if / exists within the artifactId // this is needed because we don't allow / within the artifactId artifactId = artifactId.replace('/', '_'); // Let's check whether the artifact exists ConfigurationManager configurationManager = ConfigurationUtil .getConfigurationManager(PortletManager.getKernel()); if (configurationManager.isInstalled(new Artifact(configId.getGroupId(), artifactId, configId.getVersion(), configId.getType()))) { artifactId = artifactId + "_" + new Random(System.currentTimeMillis()).nextInt(99); } configId.setArtifactId(artifactId); String[] jars = data.getJars(); int length = jars[jars.length - 1].length() == 0 ? jars.length - 1 : jars.length; org.apache.geronimo.deployment.service.jsr88.Artifact[] dependencies = new org.apache.geronimo.deployment.service.jsr88.Artifact[length]; for (int i = 0; i < dependencies.length; i++) { dependencies[i] = new org.apache.geronimo.deployment.service.jsr88.Artifact(); } environment.setDependencies(dependencies); for (int i = 0; i < dependencies.length; i++) { Artifact tmp = Artifact.create(jars[i]); dependencies[i].setGroupId(tmp.getGroupId()); dependencies[i].setArtifactId(tmp.getArtifactId()); dependencies[i].setVersion(tmp.getVersion().toString()); dependencies[i].setType(tmp.getType()); } ResourceAdapter adapter = connector.getResourceAdapter()[0]; ConnectionDefinition definition = new ConnectionDefinition(); adapter.setConnectionDefinition(new ConnectionDefinition[] { definition }); definition.setConnectionFactoryInterface("javax.sql.DataSource"); ConnectionDefinitionInstance instance = new ConnectionDefinitionInstance(); definition.setConnectionInstance(new ConnectionDefinitionInstance[] { instance }); instance.setName(data.getName()); ConfigPropertySetting[] settings = instance.getConfigPropertySetting(); if (data.isGeneric()) { // it's a generic TranQL JDBC pool for (ConfigPropertySetting setting : settings) { if (setting.getName().equals("UserName")) { setting.setValue(data.user); } else if (setting.getName().equals("Password")) { setting.setValue(data.password); } else if (setting.getName().equals("ConnectionURL")) { setting.setValue(data.url); } else if (setting.getName().equals("Driver")) { setting.setValue(data.driverClass); } } } else { // it's an XA driver or non-TranQL RA for (ConfigPropertySetting setting : settings) { String value = data.properties.get("property-" + setting.getName()); setting.setValue(value == null ? "" : value); } } ConnectionManager manager = instance.getConnectionManager(); if (XA.equals(data.transactionType)) { manager.setTransactionXA(true); } else if (NONE.equals(data.transactionType)) { manager.setTransactionNone(true); } else { manager.setTransactionLocal(true); } SinglePool pool = new SinglePool(); manager.setPoolSingle(pool); pool.setMatchOne(true); // Max Size needs to be set before the minimum. This is because // the connection manager will constrain the minimum based on the // current maximum value in the pool. We might consider adding a // setPoolConstraints method to allow specifying both at the same time. if (data.maxSize != null && !data.maxSize.equals("")) { pool.setMaxSize(new Integer(data.maxSize)); } if (data.minSize != null && !data.minSize.equals("")) { pool.setMinSize(new Integer(data.minSize)); } if (data.blockingTimeout != null && !data.blockingTimeout.equals("")) { pool.setBlockingTimeoutMillis(new Integer(data.blockingTimeout)); } if (data.idleTimeout != null && !data.idleTimeout.equals("")) { pool.setIdleTimeoutMinutes(new Integer(data.idleTimeout)); } if (planOnly) { ByteArrayOutputStream out = new ByteArrayOutputStream(); config.save(out); out.close(); return new String(out.toByteArray(), "US-ASCII"); } else { File tempFile = File.createTempFile("console-deployment", ".xml"); tempFile.deleteOnExit(); log.debug("Writing database pool deployment plan to " + tempFile.getAbsolutePath()); BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(tempFile)); config.save(out); out.flush(); out.close(); Target[] targets = mgr.getTargets(); if (null == targets) { throw new IllegalStateException("No target to distribute to"); } targets = new Target[] { targets[0] }; ProgressObject po = mgr.distribute(targets, rarFile, tempFile); waitForProgress(po); if (po.getDeploymentStatus().isCompleted()) { TargetModuleID[] ids = po.getResultTargetModuleIDs(); po = mgr.start(ids); waitForProgress(po); if (po.getDeploymentStatus().isCompleted()) { ids = po.getResultTargetModuleIDs(); if (status != null) { status.getCurrentPool().setName(data.getName()); status.getCurrentPool().setConfigurationName(ids[0].getModuleID()); status.getCurrentPool().setFinished(true); response.setRenderParameter(MODE_KEY, IMPORT_STATUS_MODE); } log.info("Deployment completed successfully!"); } } else if (po.getDeploymentStatus().isFailed()) { data.deployError = "Unable to deploy: " + data.name; response.setRenderParameter(MODE_KEY, EDIT_MODE); log.info("Deployment Failed!"); } } } catch (Exception e) { log.error("Unable to save connection pool", e); } finally { if (mgr != null) mgr.release(); } } else { // We're saving updates to an existing pool if (planOnly) { throw new UnsupportedOperationException("Can't update a plan for an existing deployment"); } try { JCAManagedConnectionFactory factory = (JCAManagedConnectionFactory) PortletManager .getManagedBean(request, new AbstractName(URI.create(data.getAbstractName()))); if (data.isGeneric()) { factory.setConfigProperty("ConnectionURL", data.getUrl()); factory.setConfigProperty("UserName", data.getUser()); factory.setConfigProperty("Password", data.getPassword()); } else { for (Map.Entry<String, String> entry : data.getProperties().entrySet()) { factory.setConfigProperty(entry.getKey().substring("property-".length()), entry.getValue()); } } /*Make pool setting effective after server restart*/ Jsr77Naming naming = new Jsr77Naming(); AbstractName connectionManagerName = naming.createChildName( new AbstractName(URI.create(data.getAbstractName())), data.getName(), NameFactory.JCA_CONNECTION_MANAGER); PoolingAttributes pool = (PoolingAttributes) PortletManager.getManagedBean(request, connectionManagerName); pool.setPartitionMinSize( data.minSize == null || data.minSize.equals("") ? 0 : Integer.parseInt(data.minSize)); pool.setPartitionMaxSize( data.maxSize == null || data.maxSize.equals("") ? 10 : Integer.parseInt(data.maxSize)); pool.setBlockingTimeoutMilliseconds( data.blockingTimeout == null || data.blockingTimeout.equals("") ? 5000 : Integer.parseInt(data.blockingTimeout)); pool.setIdleTimeoutMinutes(data.idleTimeout == null || data.idleTimeout.equals("") ? 15 : Integer.parseInt(data.idleTimeout)); } catch (Exception e) { log.error("Unable to save connection pool", e); } } return null; } private static void waitForProgress(ProgressObject po) { while (po.getDeploymentStatus().isRunning()) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } private static ImportStatus getImportStatus(PortletRequest request) { return (ImportStatus) request.getPortletSession(true).getAttribute("ImportStatus"); } private static File getRAR(PortletRequest request, String rarPath) { org.apache.geronimo.kernel.repository.Artifact artifact = org.apache.geronimo.kernel.repository.Artifact .create(rarPath); ListableRepository[] repos = PortletManager.getCurrentServer(request).getRepositories(); for (ListableRepository repo : repos) { // if the artifact is not fully resolved then try to resolve it if (!artifact.isResolved()) { SortedSet results = repo.list(artifact); if (!results.isEmpty()) { artifact = (Artifact) results.first(); } else { continue; } } File url = repo.getLocation(artifact); if (url != null) { if (url.exists() && url.canRead() && !url.isDirectory()) { return url; } } } return null; } /** * WARNING: This method relies on having access to the same repository * URLs as the server uses. * * @param request portlet request * @param data info about jars to include * @return driver class */ private static Class attemptDriverLoad(PortletRequest request, PoolData data) { List<URL> list = new ArrayList<URL>(); try { String[] jars = data.getJars(); if (jars == null) { log.error("Driver load failed since no jar files were selected."); return null; } ListableRepository[] repos = PortletManager.getCurrentServer(request).getRepositories(); for (String jar : jars) { Artifact artifact = Artifact.create(jar); for (ListableRepository repo : repos) { File url = repo.getLocation(artifact); if (url != null) { list.add(url.toURI().toURL()); } } } URLClassLoader loader = new URLClassLoader(list.toArray(new URL[list.size()]), DatabasePoolPortlet.class.getClassLoader()); try { return loader.loadClass(data.driverClass); } catch (ClassNotFoundException e) { return null; } } catch (Exception e) { e.printStackTrace(); return null; } } private static String populateURL(String url, List<String> keys, Map properties) { for (String key : keys) { String value = (String) properties.get("urlproperty-" + key); if (value == null || value.equals("")) { int begin = url.indexOf("{" + key + "}"); int end = begin + key.length() + 2; for (int j = begin - 1; j >= 0; j--) { char c = url.charAt(j); if (c == ';' || c == ':') { begin = j; break; } else if (c == '/') { if (url.length() > end && url.charAt(end) == '/') { begin = j; // Don't leave // if foo is null for /<foo>/ } break; } } url = url.substring(0, begin) + url.substring(end); } else { if (value.indexOf('\\') != -1 || value.indexOf('$') != -1) { // value contains backslash or dollar sign and needs preprocessing for replaceAll to work properly StringBuilder temp = new StringBuilder(); char[] valueChars = value.toCharArray(); for (char valueChar : valueChars) { if (valueChar == '\\' || valueChar == '$') { temp.append('\\'); } temp.append(valueChar); } value = temp.toString(); } url = url.replaceAll("\\{" + key + "\\}", value); } } return url; } private static DatabaseDriver[] getAllDrivers(PortletRequest request) { DatabaseDriver[] result = (DatabaseDriver[]) PortletManager.getGBeansImplementing(request, DatabaseDriver.class); Arrays.sort(result, new Comparator<DatabaseDriver>() { public int compare(DatabaseDriver o1, DatabaseDriver o2) { String name1 = o1.getName(); String name2 = o2.getName(); if (name1.equals("Other")) name1 = "zzzOther"; if (name2.equals("Other")) name2 = "zzzOther"; return name1.compareTo(name2); } }); return result; } private static DatabaseDriver getDatabaseInfo(PortletRequest request, PoolData data) { DatabaseDriver info = null; DatabaseDriver[] all = getAllDrivers(request); for (DatabaseDriver next : all) { if (next.getName().equals(data.getDbtype())) { info = next; break; } } return info; } private static DatabaseDriver getDatabaseInfoFromDriver(PortletRequest request, PoolData data) { DatabaseDriver info = null; DatabaseDriver[] all = getAllDrivers(request); for (DatabaseDriver next : all) { if (next.getDriverClassName() != null && next.getDriverClassName().equals(data.getDriverClass())) { info = next; break; } } return info; } public static class PoolData implements Serializable { private static final long serialVersionUID = 1L; private String name; private String dbtype; private String user; private String password; private Map<String, String> properties = new LinkedHashMap<String, String>(); // Configuration for non-Generic drivers private Map<String, Object> urlProperties = new HashMap<String, Object>(); // URL substitution for Generic drivers private Map<String, String> propertyNames; //todo: store these in the ConfigParam instead private String driverClass; private String url; private String urlPrototype; private String[] jars; private String minSize; private String maxSize; private String blockingTimeout; private String idleTimeout; private String abstractName; private String adapterDisplayName; private String adapterDescription; private String adapterRarPath; private String rarPath; private String transactionType; private String importSource; private Map<String, String> abstractNameMap; // generated as needed, don't need to read/write it private String deployError; public void load(PortletRequest request) { name = request.getParameter("name"); if (name != null && name.equals("")) name = null; driverClass = request.getParameter("driverClass"); if (driverClass != null && driverClass.equals("")) driverClass = null; dbtype = request.getParameter("dbtype"); if (dbtype != null && dbtype.equals("")) dbtype = null; user = request.getParameter("user"); if (user != null && user.equals("")) user = null; password = request.getParameter("password"); if (password != null && password.equals("")) password = null; url = request.getParameter("url"); if (url != null && url.equals("")) { url = null; } else if (url != null && url.startsWith("URLENCODED")) { try { url = URLDecoder.decode(url.substring(10), "UTF-8"); } catch (UnsupportedEncodingException e) { throw new RuntimeException("Unable to decode URL", e); } catch (IllegalArgumentException e) { // not encoded after all?? url = url.substring(10); } } urlPrototype = request.getParameter("urlPrototype"); if (urlPrototype != null && urlPrototype.equals("")) urlPrototype = null; jars = request.getParameterValues("jars"); minSize = request.getParameter("minSize"); if (minSize != null && minSize.equals("")) minSize = null; maxSize = request.getParameter("maxSize"); if (maxSize != null && maxSize.equals("")) maxSize = null; blockingTimeout = request.getParameter("blockingTimeout"); if (blockingTimeout != null && blockingTimeout.equals("")) blockingTimeout = null; idleTimeout = request.getParameter("idleTimeout"); if (idleTimeout != null && idleTimeout.equals("")) idleTimeout = null; abstractName = request.getParameter("abstractName"); if (abstractName != null && abstractName.equals("")) abstractName = null; adapterDisplayName = request.getParameter("adapterDisplayName"); if (adapterDisplayName != null && adapterDisplayName.equals("")) adapterDisplayName = null; adapterDescription = request.getParameter("adapterDescription"); if (adapterDescription != null && adapterDescription.equals("")) adapterDescription = null; rarPath = request.getParameter("rarPath"); if (rarPath != null && rarPath.equals("")) rarPath = null; importSource = request.getParameter("importSource"); if (importSource != null && importSource.equals("")) importSource = null; transactionType = request.getParameter("transactionType"); if (transactionType != null && "".equals(transactionType)) { if (dbtype != null && dbtype.endsWith("XA")) { transactionType = XA; } else { transactionType = LOCAL; } } Map map = request.getParameterMap(); propertyNames = new HashMap<String, String>(); for (Object o : map.keySet()) { String key = (String) o; if (key.startsWith("urlproperty-")) { urlProperties.put(key, request.getParameter(key)); } else if (key.startsWith("property-")) { properties.put(key, request.getParameter(key)); propertyNames.put(key, getPropertyName(key)); } } sort(); deployError = request.getParameter("deployError"); if (deployError != null && deployError.equals("")) deployError = null; } public void loadPropertyNames() { propertyNames = new HashMap<String, String>(); for (String key : properties.keySet()) { propertyNames.put(key, getPropertyName(key)); } } private static String getPropertyName(String key) { int pos = key.indexOf('-'); key = Character.toUpperCase(key.charAt(pos + 1)) + key.substring(pos + 2); StringBuilder buf = new StringBuilder(); pos = 0; for (int i = 1; i < key.length(); i++) { if (key.charAt(i) == '_') { buf.append(key.substring(pos, i)).append(" "); pos = i + 1; } else { if (Character.isUpperCase(key.charAt(i))) { if (Character.isUpperCase(key.charAt(i - 1)) || key.charAt(i - 1) == '_') { // ongoing capitalized word } else { // start of a new word buf.append(key.substring(pos, i)).append(" "); pos = i; } } else { if (Character.isUpperCase(key.charAt(i - 1)) && i - pos > 1) { // first lower-case after a series of caps buf.append(key.substring(pos, i - 1)).append(" "); pos = i - 1; } } } } buf.append(key.substring(pos)); return buf.toString(); } public void store(ActionResponse response) { if (name != null) response.setRenderParameter("name", name); if (dbtype != null) response.setRenderParameter("dbtype", dbtype); if (driverClass != null) response.setRenderParameter("driverClass", driverClass); if (user != null) response.setRenderParameter("user", user); if (password != null) response.setRenderParameter("password", password); if (url != null) { // attempt to work around Pluto/Tomcat error with ; in a stored value try { response.setRenderParameter("url", "URLENCODED" + URLEncoder.encode(url, "UTF-8")); } catch (UnsupportedEncodingException e) { throw new RuntimeException("Unable to encode URL", e); } } if (urlPrototype != null) response.setRenderParameter("urlPrototype", urlPrototype); if (jars != null) response.setRenderParameter("jars", jars); if (minSize != null) response.setRenderParameter("minSize", minSize); if (maxSize != null) response.setRenderParameter("maxSize", maxSize); if (blockingTimeout != null) response.setRenderParameter("blockingTimeout", blockingTimeout); if (idleTimeout != null) response.setRenderParameter("idleTimeout", idleTimeout); if (abstractName != null) response.setRenderParameter("abstractName", abstractName); if (adapterDisplayName != null) response.setRenderParameter("adapterDisplayName", adapterDisplayName); if (adapterDescription != null) response.setRenderParameter("adapterDescription", adapterDescription); if (importSource != null) response.setRenderParameter("importSource", importSource); if (rarPath != null) response.setRenderParameter("rarPath", rarPath); if (transactionType != null) response.setRenderParameter("transactionType", transactionType); for (Map.Entry<String, Object> entry : urlProperties.entrySet()) { if (entry.getValue() != null) { response.setRenderParameter(entry.getKey(), entry.getValue().toString()); } } for (Map.Entry<String, String> entry : properties.entrySet()) { if (entry.getValue() != null) { response.setRenderParameter(entry.getKey(), entry.getValue()); } } if (deployError != null) response.setRenderParameter("deployError", deployError); } public void sort() { Map<String, String> sortedProperties = new LinkedHashMap<String, String>(); for (String propertyName : ORDERED_PROPERTY_NAMES) { if (properties.containsKey(propertyName)) { sortedProperties.put(propertyName, properties.get(propertyName)); properties.remove(propertyName); } } sortedProperties.putAll(properties); properties = sortedProperties; } public String getName() { return name; } public String getDbtype() { return dbtype; } public String getUser() { return user; } public String getPassword() { return password; } public Map<String, String> getProperties() { return properties; } public Map<String, String> getPropertyNames() { return propertyNames; } public Map<String, Object> getUrlProperties() { return urlProperties; } public String getUrl() { return url; } public String[] getJars() { return jars; } public String getMinSize() { return minSize; } public String getMaxSize() { return maxSize; } public String getBlockingTimeout() { return blockingTimeout; } public String getIdleTimeout() { return idleTimeout; } public String getDriverClass() { return driverClass; } public String getUrlPrototype() { return urlPrototype; } public String getAbstractName() { return abstractName; } public String getAdapterDisplayName() { return adapterDisplayName; } public String getAdapterDescription() { return adapterDescription; } public String getAdapterRarPath() { return adapterRarPath; } public String getRarPath() { return rarPath; } public boolean isGeneric() { //todo: is there any better way to tell? return adapterDisplayName == null || adapterDisplayName.equals("TranQL Generic JDBC Resource Adapter"); } public String getImportSource() { return importSource; } public Map<String, String> getAbstractNameMap() { if (abstractName == null) return Collections.emptyMap(); if (abstractNameMap != null) return abstractNameMap; AbstractName name = new AbstractName(URI.create(abstractName)); abstractNameMap = new HashMap<String, String>(name.getName()); abstractNameMap.put("domain", name.getObjectName().getDomain()); abstractNameMap.put("groupId", name.getArtifact().getGroupId()); abstractNameMap.put("artifactId", name.getArtifact().getArtifactId()); abstractNameMap.put("type", name.getArtifact().getType()); abstractNameMap.put("version", name.getArtifact().getVersion().toString()); return abstractNameMap; } public String getDeployError() { return deployError; } public String getTransactionType() { return transactionType; } public void setTransactionType(String transactionType) { this.transactionType = transactionType; } } public static class ConnectionPool implements Serializable, Comparable { private static final long serialVersionUID = 1L; private final String adapterAbstractName; private final String factoryAbstractName; private final String name; private final String parentName; private final int state; public ConnectionPool(AbstractName adapterAbstractName, AbstractName factoryAbstractName, String name, int state) { this.adapterAbstractName = adapterAbstractName.toURI().toString(); String parent = (String) adapterAbstractName.getName().get(NameFactory.J2EE_APPLICATION); if (parent != null && parent.equals("null")) { parent = null; } parentName = parent; this.factoryAbstractName = factoryAbstractName.toURI().toString(); this.name = name; this.state = state; } public String getAdapterAbstractName() { return adapterAbstractName; } public String getFactoryAbstractName() { return factoryAbstractName; } public String getName() { return name; } public String getParentName() { return parentName; } public int getState() { return state; } public String getStateName() { return State.toString(state); } public int compareTo(Object o) { final ConnectionPool pool = (ConnectionPool) o; int names = name.compareTo(pool.name); if (parentName == null) { if (pool.parentName == null) { return names; } else { return -1; } } else { if (pool.parentName == null) { return 1; } else { int test = parentName.compareTo(pool.parentName); if (test != 0) { return test; } else { return names; } } } } } public static class ResourceAdapterParams { private String displayName; private String description; private String rarPath; private ConfigParam[] configParams; public ResourceAdapterParams(String displayName, String description, String rarPath, ConfigParam[] configParams) { this.displayName = displayName; this.description = description; this.rarPath = rarPath; this.configParams = configParams; } public String getDisplayName() { return displayName; } public String getDescription() { return description; } public String getRarPath() { return rarPath; } public ConfigParam[] getConfigParams() { return configParams; } } public static class ConfigParam { private String name; private String type; private String description; private String defaultValue; public ConfigParam(String name, String type, String description, String defaultValue) { this.name = name; this.type = type; this.description = description; this.defaultValue = defaultValue; } public String getName() { return name; } public String getType() { return type; } public String getDescription() { return description; } public String getDefaultValue() { return defaultValue; } } }