org.glassfish.resources.admin.cli.ResourcesXMLParser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of payara-micro Show documentation
Show all versions of payara-micro Show documentation
Micro Distribution of the Payara Project for IBM JDK
/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development * and Distribution License("CDDL") (collectively, the "License"). You * may not use this file except in compliance with the License. You can * obtain a copy of the License at * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html * or packager/legal/LICENSE.txt. See the License for the specific * language governing permissions and limitations under the License. * * When distributing the software, include this License Header Notice in each * file and include the License file at packager/legal/LICENSE.txt. * * GPL Classpath Exception: * Oracle designates this particular file as subject to the "Classpath" * exception as provided by Oracle in the GPL Version 2 section of the License * file that accompanied this code. * * Modifications: * If applicable, add the following below the License Header, with the fields * enclosed by brackets [] replaced by your own identifying information: * "Portions Copyright [year] [name of copyright owner]" * * Contributor(s): * If you wish your version of this file to be governed by only the CDDL or * only the GPL Version 2, indicate your decision by adding "[Contributor] * elects to include this software in this distribution under the [CDDL or GPL * Version 2] license." If you don't indicate a single choice of license, a * recipient has the option to distribute your version of this file under * either the CDDL, the GPL Version 2 or to extend the choice of license to * its licensees as provided above. However, if you add GPL Version 2 code * and therefore, elected the GPL Version 2 license, then the option applies * only if the new code is made subject to such option by the copyright * holder. */ // Portions Copyright [2017] [Payara Foundation and/or its affiliates] package org.glassfish.resources.admin.cli; import com.sun.enterprise.util.SystemPropertyConstants; import com.sun.enterprise.util.i18n.StringManager; import org.glassfish.api.I18n; import org.glassfish.resources.api.Resource; import org.w3c.dom.*; import org.xml.sax.*; import org.xml.sax.ext.LexicalHandler; import javax.xml.parsers.*; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import java.io.*; import java.net.URL; import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; import static org.glassfish.resources.admin.cli.ResourceConstants.*; //i18n import /** * This Class reads the Properties (resources) from the xml file supplied * to constructor */ @I18n("resources.parser") public class ResourcesXMLParser implements EntityResolver { private File resourceFile = null; private Document document; private List
objects in the order as defined * in the resources XML configuration file. Maintained for backward compat * purposes only. */ public IteratorvResources; private Map resourceMap = new HashMap (); private boolean isDoctypePresent = false; /* list of resources that needs to be created prior to module deployment. This * includes all non-Connector resources and resource-adapter-config */ // private List connectorResources; /* Includes all connector resources in the order in which the resources needs to be created */ // private List nonConnectorResources; // i18n StringManager private static StringManager localStrings = StringManager.getManager( ResourcesXMLParser.class ); private static final int NONCONNECTOR = 2; private static final int CONNECTOR = 1; private static final Logger _logger = Logger.getLogger(ResourcesXMLParser.class.getName()); private static final String SUN_RESOURCES = "sun-resources"; public static final String JAVA_APP_SCOPE_PREFIX = "java:app/"; public static final String JAVA_COMP_SCOPE_PREFIX = "java:comp/"; public static final String JAVA_MODULE_SCOPE_PREFIX = "java:module/"; public static final String JAVA_GLOBAL_SCOPE_PREFIX = "java:global/"; /** * List of naming scopes */ public static final List namingScopes = Collections.unmodifiableList( Arrays.asList( JAVA_APP_SCOPE_PREFIX, JAVA_COMP_SCOPE_PREFIX, JAVA_MODULE_SCOPE_PREFIX, JAVA_GLOBAL_SCOPE_PREFIX )); private static final String publicID_sjsas90 = "Sun Microsystems, Inc.//DTD Application Server 9.0 Resource Definitions"; private static final String publicID_ges30 = "Sun Microsystems, Inc.//DTD GlassFish Application Server 3.0 Resource Definitions"; private static final String publicID_ges31 = "GlassFish.org//DTD GlassFish Application Server 3.1 Resource Definitions"; private static final String DTD_1_5 = "glassfish-resources_1_5.dtd"; private static final String DTD_1_4 = "sun-resources_1_4.dtd"; private static final String DTD_1_3 = "sun-resources_1_3.dtd"; private static final String DTD_1_2 = "sun-resources_1_2.dtd"; private static final String DTD_1_1 = "sun-resources_1_1.dtd"; private static final String DTD_1_0 = "sun-resources_1_0.dtd"; private static final List systemIDs = Collections.unmodifiableList( Arrays.asList( DTD_1_5, DTD_1_4, DTD_1_3, DTD_1_2, DTD_1_1, DTD_1_0 )); /** Creates new ResourcesXMLParser */ public ResourcesXMLParser(File resourceFile) throws Exception { this.resourceFile = resourceFile; initProperties(); vResources = new ArrayList (); String scope = ""; generateResourceObjects(scope); } /** Creates new ResourcesXMLParser */ public ResourcesXMLParser(File resourceFile, String scope) throws Exception { this.resourceFile = resourceFile; initProperties(); vResources = new ArrayList (); generateResourceObjects(scope); } /** * Persist the XML file. * @param to target location */ public void persist(File to) { // now serialize to a file. FileOutputStream out = null; try { String systemValue = (new File(document.getDoctype().getSystemId())).getName(); Transformer transformer = TransformerFactory.newInstance().newTransformer(); transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, systemValue); out = new FileOutputStream(to); transformer.transform(new DOMSource(document), new StreamResult(out)); } catch (Exception ex) { _logger.log(Level.WARNING, ex.getMessage(), ex); } finally { if (out != null) { try { out.close(); } catch (Exception ex) { _logger.warning(ex.getMessage()); } } } } // update the document node with modified resource public void updateDocumentNode(Resource originalResource, Resource modifiedResource) { Node resourceNode = resourceMap.remove(originalResource); // Remove all the existing property nodes. while (resourceNode.hasChildNodes()) { resourceNode.removeChild(resourceNode.getFirstChild()); } HashMap attrs = modifiedResource.getAttributes(); Iterator entries = attrs.entrySet().iterator(); while (entries.hasNext()) { Map.Entry thisEntry = (Map.Entry) entries.next(); ((Element)resourceNode).setAttribute((String) thisEntry.getKey(), (String)thisEntry.getValue()); } // Put the new/modified property nodes. Properties props = modifiedResource.getProperties(); for (String key : props.stringPropertyNames()) { String val = props.getProperty(key); org.w3c.dom.Element prop = document.createElement("property"); prop.setAttribute("name", key); prop.setAttribute("value", val); resourceNode.appendChild(prop); } // update the map resourceMap.put(modifiedResource, resourceNode); } public File getResourceFile() { return resourceFile; } /** *Parse the XML Properties file and populate it into document object */ private void initProperties() throws Exception { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); BufferedInputStream bis = null; FileInputStream fis = null; try { AddResourcesErrorHandler errorHandler = new AddResourcesErrorHandler(); factory.setValidating(true); DocumentBuilder builder = factory.newDocumentBuilder(); builder.setEntityResolver(this); builder.setErrorHandler(errorHandler); Object args[] = new Object[]{resourceFile}; if (resourceFile == null) { String msg = localStrings.getStringWithDefault( "resources.parser.no_resource_file", "Resource file ({0} does not exist", args ); throw new Exception( msg ); } fis = new FileInputStream(resourceFile); InputSource is = new InputSource(fis); document = builder.parse(is); detectDeprecatedDescriptor(); }/*catch(SAXParseException saxpe){ throw new Exception(saxpe.getLocalizedMessage()); }*/catch (SAXException sxe) { //This check is introduced to check if DOCTYPE is present in sun-resources.xml //And throw proper error message if DOCTYPE is missing try { SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser sp = spf.newSAXParser(); sp.setProperty("http://xml.org/sax/properties/lexical-handler", new MyLexicalHandler()); //we need to open the same file. Close it to be safe. if(fis != null){ try{ fis.close(); fis = null; }catch(Exception e){ //ignore } } fis = new FileInputStream(resourceFile); sp.getXMLReader().parse(new InputSource(fis)); } catch (ParserConfigurationException ex) { } catch (SAXException ex) { } catch (IOException ex) { } if(!isDoctypePresent){ Object args[] = new Object[]{resourceFile.toString()}; throw new Exception( localStrings.getStringWithDefault("resources.parser.doctype_not_present_in_xml", "Error Parsing the xml ({0}), doctype is not present", args)); } Exception x = sxe; if (sxe.getException() != null) x = sxe.getException(); throw new Exception(x.getLocalizedMessage()); } catch (ParserConfigurationException pce) { // Parser with specified options can't be built throw new Exception(pce.getLocalizedMessage()); } catch (IOException ioe) { throw new Exception(ioe.getLocalizedMessage()); }finally{ if(fis != null){ try{ fis.close(); }catch(Exception e){ //ignore } } } } /** * detects and logs a warning if any of the deprecated descriptor (sun-resources*.dtd) is specified */ private void detectDeprecatedDescriptor() { String publicId = document.getDoctype().getPublicId(); String systemId = document.getDoctype().getSystemId(); if( (publicId != null && publicId.contains(SUN_RESOURCES)) || (systemId != null && systemId.contains(SUN_RESOURCES))){ String msg = localStrings.getString( "deprecated.resources.dtd", resourceFile.getAbsolutePath() ); _logger.log(Level.FINEST, msg); } } /** * Get All the resources from the document object. * */ private void generateResourceObjects(String scope) throws Exception { if (document != null) { for (Node nextKid = document.getDocumentElement().getFirstChild(); nextKid != null; nextKid = nextKid.getNextSibling()) { String nodeName = nextKid.getNodeName(); if (nodeName.equalsIgnoreCase(Resource.CUSTOM_RESOURCE)) { generateCustomResource(nextKid, scope); } else if (nodeName.equalsIgnoreCase(org.glassfish.resources.api.Resource.EXTERNAL_JNDI_RESOURCE)) { generateJNDIResource(nextKid, scope); } else if (nodeName.equalsIgnoreCase(org.glassfish.resources.api.Resource.JDBC_RESOURCE)) { generateJDBCResource(nextKid, scope); } else if (nodeName.equalsIgnoreCase(org.glassfish.resources.api.Resource.JDBC_CONNECTION_POOL)) { generateJDBCConnectionPoolResource(nextKid, scope); } else if (nodeName.equalsIgnoreCase(Resource.MAIL_RESOURCE)) { generateMailResource(nextKid, scope); } //PMF resource is no more supported and hence removing support form sun-resources.xml else if (nodeName.equalsIgnoreCase(org.glassfish.resources.api.Resource.PERSISTENCE_MANAGER_FACTORY_RESOURCE)) { generatePersistenceResource(nextKid); _logger.log(Level.FINEST, "persistence-manager-factory-resource is no more supported " + ", ignoring the resource description"); } else if (nodeName.equalsIgnoreCase(Resource.ADMIN_OBJECT_RESOURCE)) { generateAdminObjectResource(nextKid, scope); } else if (nodeName.equalsIgnoreCase(Resource.CONNECTOR_RESOURCE)) { generateConnectorResource(nextKid, scope); } else if (nodeName.equalsIgnoreCase(org.glassfish.resources.api.Resource.CONNECTOR_CONNECTION_POOL)) { generateConnectorConnectionPoolResource(nextKid, scope); } else if (nodeName.equalsIgnoreCase(org.glassfish.resources.api.Resource.RESOURCE_ADAPTER_CONFIG)) { generateResourceAdapterConfig(nextKid, scope); } else if (nodeName.equalsIgnoreCase(org.glassfish.resources.api.Resource.CONNECTOR_WORK_SECURITY_MAP)) { generateWorkSecurityMap(nextKid, scope); } } } } /** * Sorts the resources defined in the resources configuration xml file into * two buckets * a) list of resources that needs to be created prior to * module deployment. This includes all non-Connector resources * and resource-adapter-config * b) includes all connector resources in the order in which the resources needs * to be created * and returns the requested resources bucker to the caller. * * @param resources Resources list as defined in sun-resources.xml * @param type Specified either ResourcesXMLParser.CONNECTOR or * ResourcesXMLParser.NONCONNECTOR to indicate the type of * resources are needed by the client of the ResourcesXMLParser * @param isResourceCreation During the resource Creation Phase, RA configs are * added to the nonConnector resources list so that they can be created in the * PreResCreationPhase
. When the isResourceCreation is false, the * RA config resuorces are added to the Connector Resources list, so that they * can be deleted as all other connector resources in the *PreResDeletionPhase
*/ private static ListgetResourcesOfType(List resources, int type, boolean isResourceCreation, boolean ignoreDuplicates) { List nonConnectorResources = new ArrayList (); List connectorResources = new ArrayList (); for (Resource res : resources) { if (isConnectorResource(res)) { if (res.getType().equals(Resource.RESOURCE_ADAPTER_CONFIG)) { if(isResourceCreation) { //RA config is considered as a nonConnector Resource, //during sun-resources.xml resource-creation phase, so that //it could be created before the RAR is deployed. addToList(nonConnectorResources, res, ignoreDuplicates); } else { addToList(connectorResources, res, ignoreDuplicates); } } else { addToList(connectorResources, res, ignoreDuplicates); } } else { addToList(nonConnectorResources, res, ignoreDuplicates); } } List finalSortedConnectorList = sortConnectorResources(connectorResources); List finalSortedNonConnectorList = sortNonConnectorResources(nonConnectorResources); if (type == CONNECTOR) { return finalSortedConnectorList; } else { return finalSortedNonConnectorList; } } private static void addToList(List resources, Resource res, boolean ignoreDuplicates){ if(ignoreDuplicates){ if(!resources.contains(res)){ resources.add(res); } }else{ resources.add(res); } } /** * Sort connector resources * Resource Adapter configs are added first. * Pools are then added to the list, so that the connection * pools can be created prior to any other connector resource defined * in the resources configuration xml file. * @param connectorResources List of Resources to be sorted. * @return The sorted list. */ private static List sortConnectorResources(List connectorResources) { List raconfigs = new ArrayList (); List ccps = new ArrayList (); List others = new ArrayList (); List finalSortedConnectorList = new ArrayList (); for (Resource resource : connectorResources) { if (resource.getType().equals(org.glassfish.resources.api.Resource.RESOURCE_ADAPTER_CONFIG)){ raconfigs.add(resource); } else if (resource.getType().equals(org.glassfish.resources.api.Resource.CONNECTOR_CONNECTION_POOL)) { ccps.add(resource); } else { others.add(resource); } } finalSortedConnectorList.addAll(raconfigs); finalSortedConnectorList.addAll(ccps); finalSortedConnectorList.addAll(others); return finalSortedConnectorList; } /** * Sort non connector resources * JDBC Pools are added first to the list, so that the conncetion * pools can be created prior to any other jdbc resource defined * in the resources configuration xml file. * @param nonConnectorResources List of Resources to be sorted. * @return The sorted list. */ private static List sortNonConnectorResources(List nonConnectorResources) { List jdbccps = new ArrayList (); List pmfs = new ArrayList (); List others = new ArrayList (); List finalSortedNonConnectorList = new ArrayList (); for (Resource resource : nonConnectorResources) { if(resource.getType().equals(org.glassfish.resources.api.Resource.JDBC_CONNECTION_POOL)) { jdbccps.add(resource); } else if(resource.getType().equals(org.glassfish.resources.api.Resource.PERSISTENCE_MANAGER_FACTORY_RESOURCE)) { //TODO throw exception as pmf resource is not supported anymore pmfs.add(resource); } else { others.add(resource); } } finalSortedNonConnectorList.addAll(jdbccps); finalSortedNonConnectorList.addAll(others); finalSortedNonConnectorList.addAll(pmfs); return finalSortedNonConnectorList; } /** * Determines if the passed in Resource
is a connector * resource. A connector resource is either a connector connection pool or a * connector resource, security map, ra config or an admin object * * @param res Resource that needs to be tested * @return */ private static boolean isConnectorResource(Resource res) { String type = res.getType(); return ( (type.equals(Resource.ADMIN_OBJECT_RESOURCE)) || (type.equals(org.glassfish.resources.api.Resource.CONNECTOR_CONNECTION_POOL)) || (type.equals(org.glassfish.resources.api.Resource.CONNECTOR_RESOURCE)) || (type.equals(org.glassfish.resources.api.Resource.CONNECTOR_SECURITY_MAP)) || (type.equals(org.glassfish.resources.api.Resource.RESOURCE_ADAPTER_CONFIG)) ); } private String getScopedName(String name, String scope) throws Exception{ if(namingScopes.contains(scope)){ if(name != null){ for(String namingScope : namingScopes){ Object args[] = new Object[]{name, namingScope, scope}; if(name.startsWith(namingScope) && !namingScope.equals(scope)){ String msg = localStrings.getStringWithDefault( "invalid.scope.defined.for.resource", "Resource [ {0} ] is not allowed to specify the scope " + "[ {1} ]. Acceptable scope for this resource" + " is [ {2} ]", args ); throw new IllegalStateException(msg); } } if(!name.startsWith(scope)){ name = scope + name; } } } return name; } private void generatePersistenceResource(Node nextKid) throws Exception { NamedNodeMap attributes = nextKid.getAttributes(); if (attributes == null) return; Node jndiNameNode = attributes.getNamedItem(JNDI_NAME); String jndiName = jndiNameNode.getNodeValue(); Node factoryClassNode = attributes.getNamedItem(FACTORY_CLASS); Node poolNameNode = attributes.getNamedItem(JDBC_RESOURCE_JNDI_NAME); Node enabledNode = attributes.getNamedItem(ENABLED); Resource persistenceResource = new org.glassfish.resources.api.Resource(org.glassfish.resources.api.Resource.PERSISTENCE_MANAGER_FACTORY_RESOURCE); persistenceResource.setAttribute(JNDI_NAME, jndiName); if (factoryClassNode != null) { String factoryClass = factoryClassNode.getNodeValue(); persistenceResource.setAttribute(FACTORY_CLASS, factoryClass); } if (poolNameNode != null) { String poolName = poolNameNode.getNodeValue(); persistenceResource.setAttribute(JDBC_RESOURCE_JNDI_NAME, poolName); } if (enabledNode != null) { String sEnabled = enabledNode.getNodeValue(); persistenceResource.setAttribute(ENABLED, sEnabled); } NodeList children = nextKid.getChildNodes(); generatePropertyElement(persistenceResource, children); vResources.add(persistenceResource); resourceMap.put(persistenceResource, nextKid); //debug strings printResourceElements(persistenceResource); } /* * Generate the Custom resource */ private void generateCustomResource(Node nextKid, String scope) throws Exception { NamedNodeMap attributes = nextKid.getAttributes(); if (attributes == null) return; Node jndiNameNode = attributes.getNamedItem(JNDI_NAME); String jndiName = getScopedName(jndiNameNode.getNodeValue(), scope); Node resTypeNode = attributes.getNamedItem(RES_TYPE); String resType = resTypeNode.getNodeValue(); Node factoryClassNode = attributes.getNamedItem(FACTORY_CLASS); String factoryClass = factoryClassNode.getNodeValue(); Node enabledNode = attributes.getNamedItem(ENABLED); Resource customResource = new Resource(Resource.CUSTOM_RESOURCE); customResource.setAttribute(JNDI_NAME, jndiName); customResource.setAttribute(RES_TYPE, resType); customResource.setAttribute(FACTORY_CLASS, factoryClass); if (enabledNode != null) { String sEnabled = enabledNode.getNodeValue(); customResource.setAttribute(ENABLED, sEnabled); } NodeList children = nextKid.getChildNodes(); generatePropertyElement(customResource, children); vResources.add(customResource); resourceMap.put(customResource, nextKid); //debug strings printResourceElements(customResource); } /** * Generate the JNDI resource */ private void generateJNDIResource(Node nextKid, String scope) throws Exception { NamedNodeMap attributes = nextKid.getAttributes(); if (attributes == null) return; Node jndiNameNode = attributes.getNamedItem(JNDI_NAME); String jndiName = getScopedName(jndiNameNode.getNodeValue(), scope); Node jndiLookupNode = attributes.getNamedItem(JNDI_LOOKUP); String jndiLookup = jndiLookupNode.getNodeValue(); Node resTypeNode = attributes.getNamedItem(RES_TYPE); String resType = resTypeNode.getNodeValue(); Node factoryClassNode = attributes.getNamedItem(FACTORY_CLASS); String factoryClass = factoryClassNode.getNodeValue(); Node enabledNode = attributes.getNamedItem(ENABLED); org.glassfish.resources.api.Resource jndiResource = new Resource(Resource.EXTERNAL_JNDI_RESOURCE); jndiResource.setAttribute(JNDI_NAME, jndiName); jndiResource.setAttribute(JNDI_LOOKUP, jndiLookup); jndiResource.setAttribute(RES_TYPE, resType); jndiResource.setAttribute(FACTORY_CLASS, factoryClass); if (enabledNode != null) { String sEnabled = enabledNode.getNodeValue(); jndiResource.setAttribute(ENABLED, sEnabled); } NodeList children = nextKid.getChildNodes(); generatePropertyElement(jndiResource, children); vResources.add(jndiResource); resourceMap.put(jndiResource, nextKid); //debug strings printResourceElements(jndiResource); } /** * Generate the JDBC resource */ private void generateJDBCResource(Node nextKid, String scope) throws Exception { NamedNodeMap attributes = nextKid.getAttributes(); if (attributes == null) return; Node jndiNameNode = attributes.getNamedItem(JNDI_NAME); String jndiName = getScopedName(jndiNameNode.getNodeValue(), scope); Node poolNameNode = attributes.getNamedItem(POOL_NAME); String poolName = getScopedName(poolNameNode.getNodeValue(), scope); Node enabledNode = attributes.getNamedItem(ENABLED); Resource jdbcResource = new org.glassfish.resources.api.Resource(org.glassfish.resources.api.Resource.JDBC_RESOURCE); jdbcResource.setAttribute(JNDI_NAME, jndiName); jdbcResource.setAttribute(POOL_NAME, poolName); if (enabledNode != null) { String enabledName = enabledNode.getNodeValue(); jdbcResource.setAttribute(ENABLED, enabledName); } NodeList children = nextKid.getChildNodes(); //get description if (children != null) { for (int ii=0; iiResource getResources() { return vResources.iterator(); } public List getResourcesList() { return vResources; } /** * Returns an List of Resource
objects that needs to be * created prior to module deployment. This includes all non-Connector * resources and resource-adapter-config * @param resources List of resources, from which the non connector * resources need to be obtained. * @param isResourceCreation indicates if this determination needs to be * done during thePreResCreationPhase
. In the *PreResCreationPhase
, RA config is added to the * non connector list, so that the RA config is created prior to the * RA deployment. For all other purpose, this flag needs to be set to false. */ public static List getNonConnectorResourcesList(Listresources, boolean isResourceCreation, boolean ignoreDuplicates) { return getResourcesOfType(resources, NONCONNECTOR, isResourceCreation, ignoreDuplicates); } /** * Returns an Iterator of Resource
objects that correspond to * connector resources that needs to be created post module deployment. They * are arranged in the order in which the resources needs to be created * @param resources List of resources, from which the non connector * resources need to be obtained. * @param isResourceCreation indicates if this determination needs to be * done during thePreResCreationPhase
. In the *PreResCreationPhase
, RA config is added to the * non connector list, so that the RA config is created prior to the * RA deployment. For all other purpose, this flag needs to be set to false. */ public static List getConnectorResourcesList(Listresources, boolean isResourceCreation, boolean ignoreDuplicates) { return getResourcesOfType(resources, CONNECTOR, isResourceCreation, ignoreDuplicates); } /** * Print(Debug) the resource */ private void printResourceElements(Resource resource) { HashMap attrList = resource.getAttributes(); Iterator attrIter = attrList.keySet().iterator(); while (attrIter.hasNext()) { String attrName = (String)attrIter.next(); Logger.getLogger(ResourcesXMLParser.class.getName()).log( Level.FINE, "Name of the attribute:[{0}]", attrName); } } // Helper Method to convert a String type to a String[] private String[] convertToStringArray(Object sOptions){ StringTokenizer optionTokenizer = new StringTokenizer((String)sOptions,","); int size = optionTokenizer.countTokens(); String [] sOptionsList = new String[size]; for (int ii=0; ii
© 2015 - 2024 Weber Informatics LLC | Privacy Policy