Java tutorial
/* * Copyright (c) 2006, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * Licensed 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.wso2.carbon.governance.lcm.util; import org.apache.axiom.om.*; import org.apache.axiom.om.util.AXIOMUtil; import org.apache.axiom.om.xpath.AXIOMXPath; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.CarbonConstants; import org.wso2.carbon.governance.lcm.beans.LifecycleBean; import org.wso2.carbon.governance.lcm.internal.LifeCycleServiceHolder; import org.wso2.carbon.registry.core.*; import org.wso2.carbon.registry.core.Collection; import org.wso2.carbon.registry.core.config.RegistryConfigurationProcessor; import org.wso2.carbon.registry.core.config.RegistryContext; import org.wso2.carbon.registry.core.config.StaticConfiguration; import org.wso2.carbon.registry.core.exceptions.RegistryException; import org.wso2.carbon.registry.core.session.UserRegistry; import org.wso2.carbon.registry.core.utils.RegistryUtils; import org.wso2.carbon.utils.CarbonUtils; import org.wso2.carbon.utils.ServerConstants; import org.xml.sax.SAXException; import javax.xml.XMLConstants; import javax.xml.namespace.QName; import javax.xml.stream.XMLStreamException; import javax.xml.transform.Source; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import javax.xml.validation.Validator; import java.io.*; import java.util.*; public class CommonUtil { private static final Log log = LogFactory.getLog(CommonUtil.class); private static String contextRoot = null; // Lifecycle property search query. public static final String searchLCMPropertiesQuery = RegistryConstants.QUERIES_COLLECTION_PATH + "/governance/searchLCMProperties"; private static Validator lifecycleSchemaValidator = null; public static UserRegistry getRootSystemRegistry() throws RegistryException { if (LifeCycleServiceHolder.getInstance().getRegistryService() == null) { return null; } else { return LifeCycleServiceHolder.getInstance().getRegistryService() .getRegistry(CarbonConstants.REGISTRY_SYSTEM_USERNAME); } } public static UserRegistry getRootSystemRegistry(int tenantId) throws RegistryException { if (LifeCycleServiceHolder.getInstance().getRegistryService() == null) { return null; } else { return LifeCycleServiceHolder.getInstance().getRegistryService() .getRegistry(CarbonConstants.REGISTRY_SYSTEM_USERNAME, tenantId); } } /*public static UserRegistry getRegistry() throws RegistryException { MessageContext messageContext = MessageContext.getCurrentMessageContext(); if (messageContext == null) { String msg = "Could not get the user's Registry session. Message context not found."; log.error(msg); throw new RegistryException(msg); } HttpServletRequest request = (HttpServletRequest) messageContext.getProperty("transport.http.servletRequest"); return getRegistry(request); } public static UserRegistry getRegistry(HttpServletRequest request) throws RegistryException { UserRegistry registry = (UserRegistry) request.getSession().getAttribute(RegistryConstants.USER_REGISTRY); if (registry == null) { String msg = "User's Registry instance is not found. " + "Users have to login to retrieve a registry instance. "; log.error(msg); throw new RegistryException(msg); } return registry; } public static UserRegistry getSystemRegistry() throws RegistryException { MessageContext messageContext = MessageContext.getCurrentMessageContext(); if (messageContext == null) { String msg = "Could not get the user's Registry session. Message context not found."; log.error(msg); throw new RegistryException(msg); } HttpServletRequest request = (HttpServletRequest) messageContext.getProperty("transport.http.servletRequest"); UserRegistry registry = (UserRegistry) request.getSession().getAttribute(RegistryConstants.SYSTEM_REGISTRY); if (registry == null) { String msg = "System Registry instance is not found. " + "Users have to login to retrieve a system registry instance for the tenant. "; log.error(msg); throw new RegistryException(msg); } return registry; }*/ public static boolean updateLifecycle(String oldName, LifecycleBean bean, Registry registry, Registry rootRegistry) throws RegistryException, XMLStreamException { String payload = LifecycleBeanPopulator.serializeLifecycleBean(bean); return updateLifecycle(oldName, payload, registry, rootRegistry); } public static boolean updateLifecycle(String oldName, String payload, Registry registry, Registry rootRegistry) throws RegistryException, XMLStreamException { String newName = null; OMElement element = buildOMElement(payload); // We have added an validation here too since someone can directly call this method validateOMContent(element); if (element != null) { newName = element.getAttributeValue(new QName("name")); } if (newName == null || newName.equals("")) return false; // invalid configuration if (oldName == null || oldName.equals("")) { String path = getContextRoot() + newName; Resource resource; if (lifeCycleExists(newName, registry)) { return false; // we are adding a new lifecycle } else { resource = new ResourceImpl(); } resource.setContent(payload); try { registry.beginTransaction(); registry.put(path, resource); generateAspect(path, registry); registry.commitTransaction(); } catch (Exception e) { registry.rollbackTransaction(); String errorMsg = "Unable to update aspect. "; if (e.getCause() instanceof ClassNotFoundException) { errorMsg += "Could not find class " + e.getCause().getMessage(); } else if (e.getCause() instanceof com.ctc.wstx.exc.WstxParsingException) { errorMsg += e.getCause().getMessage(); } throw new RegistryException(errorMsg, e); } return true; } if (newName.equals(oldName)) { //updating the rest of the content String oldPath = getContextRoot() + oldName; Resource resource; if (lifeCycleExists(oldName, registry)) { resource = registry.get(oldPath); } else { resource = new ResourceImpl(); // will this ever happen? } resource.setContent(payload); try { registry.beginTransaction(); registry.put(oldPath, resource); generateAspect(oldPath, registry); registry.commitTransaction(); } catch (Exception e) { registry.rollbackTransaction(); String errorMsg = "Unable to update aspect. "; if (e.getCause() instanceof ClassNotFoundException) { errorMsg += "Could not find class " + e.getCause().getMessage(); } else if (e.getCause() instanceof com.ctc.wstx.exc.WstxParsingException) { errorMsg += e.getCause().getMessage(); } throw new RegistryException(errorMsg, e); } return true; } else { String oldPath = getContextRoot() + oldName; String newPath = getContextRoot() + newName; if (lifeCycleExists(newName, registry)) { return false; // we are trying to use the name of a existing lifecycle } Resource resource; if (lifeCycleExists(oldName, registry)) { resource = registry.get(oldPath); } else { resource = new ResourceImpl(); // will this ever happen? } resource.setContent(payload); try { registry.beginTransaction(); registry.put(newPath, resource); generateAspect(newPath, registry); registry.delete(oldPath); removeAspect(oldName, registry); registry.commitTransaction(); } catch (Exception e) { registry.rollbackTransaction(); throw new RegistryException("Unable to renew aspect", e); } return true; } } public static boolean createLifecycle(String configuration, Registry registry, Registry rootRegistry) throws RegistryException, XMLStreamException { // String configuration = LifecycleBeanPopulator.serializeLifecycleBean(bean); return addLifecycle(configuration, registry, rootRegistry); } public static boolean addLifecycle(String payload, Registry registry, Registry rootRegistry) throws RegistryException, XMLStreamException { String name; OMElement element = null; element = buildOMElement(payload); // We have added an validation here too since someone can directly call this method validateOMContent(element); name = element.getAttributeValue(new QName("name")); if (isLifecycleNameInUse(name, registry, rootRegistry)) { String msg = String.format("The lifecycle name %s is already in use", name); throw new RegistryException(msg); } String path = getContextRoot() + name; Resource resource; if (!lifeCycleExists(name, registry)) { resource = new ResourceImpl(); } else { return false; // Already existing resource. } resource.setContent(payload); try { registry.beginTransaction(); registry.put(path, resource); generateAspect(path, registry); registry.commitTransaction(); } catch (Exception e) { registry.rollbackTransaction(); String errorMsg = "Unable to initiate aspect. "; if (e.getCause() instanceof ClassNotFoundException) { errorMsg += "Could not find class " + e.getCause().getMessage(); } else if (e.getCause() instanceof com.ctc.wstx.exc.WstxParsingException) { errorMsg += e.getCause().getMessage(); } throw new RegistryException(errorMsg.replaceAll("<", "<").replaceAll(">", ">"), e); } return true; } public static void validateOMContent(OMElement element) throws RegistryException { if (!validateOMContent(element, getLifecycleSchemaValidator(getLifecycleSchemaLocation()))) { String message = "Unable to validate the lifecycle configuration"; log.error(message); throw new RegistryException(message); } } public static OMElement buildOMElement(String payload) throws RegistryException { OMElement element; try { element = AXIOMUtil.stringToOM(payload); element.build(); } catch (Exception e) { String message = "Unable to parse the XML configuration. Please validate the XML configuration"; log.error(message, e); throw new RegistryException(message, e); } return element; } public static boolean lifeCycleExists(String name, Registry registry) throws RegistryException { return registry.resourceExists(getContextRoot() + name); } public static boolean deleteLifecycle(String name, Registry registry, Registry rootRegistry) throws RegistryException, XMLStreamException { if (isLifecycleNameInUse(name, registry, rootRegistry)) throw new RegistryException("Lifecycle could not be deleted, since it is already in use!"); String path = getContextRoot() + name; if (registry.resourceExists(path)) { try { registry.beginTransaction(); registry.delete(path); removeAspect(name, registry); registry.commitTransaction(); } catch (Exception e) { registry.rollbackTransaction(); throw new RegistryException("Unable to remove aspect", e); } return true; } return false; } public static String getLifecycleConfiguration(String name, Registry registry) throws RegistryException, XMLStreamException { String path = getContextRoot() + name; Resource resource; if (lifeCycleExists(name, registry)) { resource = registry.get(path); return RegistryUtils.decodeBytes((byte[]) resource.getContent()); } return null; } public static String getLifecycleConfigurationVersion(String name, Registry registry) throws RegistryException, XMLStreamException { String path = getContextRoot() + name; Resource resource; if (lifeCycleExists(name, registry)) { resource = registry.get(path); return String.valueOf(((ResourceImpl) resource).getVersionNumber()); } return null; } public static boolean generateAspect(String resourceFullPath, Registry registry) throws RegistryException, XMLStreamException { RegistryContext registryContext = registry.getRegistryContext(); if (registryContext == null) { return false; } Resource resource = registry.get(resourceFullPath); if (resource != null) { String content = null; if (resource.getContent() != null) { content = RegistryUtils.decodeBytes((byte[]) resource.getContent()); } if (content != null) { OMElement aspect = AXIOMUtil.stringToOM(content); if (aspect != null) { OMElement dummy = OMAbstractFactory.getOMFactory().createOMElement("dummy", null); dummy.addChild(aspect); Aspect aspectinstance = RegistryConfigurationProcessor.updateAspects(dummy); Iterator aspectElement = dummy.getChildrenWithName(new QName("aspect")); String name = ""; if (aspectElement != null) { OMElement aspectelement = (OMElement) aspectElement.next(); name = aspectelement.getAttributeValue(new QName("name")); } registry.addAspect(name, aspectinstance); return true; } } } return false; } public static boolean removeAspect(String aspectname, Registry registry) throws RegistryException { return registry.removeAspect(aspectname); } public static String[] getLifecycleList(Registry registry) throws RegistryException { Collection collection; try { collection = (Collection) registry.get(getContextRoot()); } catch (Exception e) { return null; } if (collection == null) { CollectionImpl lifeCycleCollection = new CollectionImpl(); registry.put(getContextRoot(), lifeCycleCollection); return null; } else { if (collection.getChildCount() == 0) { return null; } String[] childrenList = collection.getChildren(); String[] lifeCycleNameList = new String[collection.getChildCount()]; for (int i = 0; i < childrenList.length; i++) { String path = childrenList[i]; lifeCycleNameList[i] = path.substring(path.lastIndexOf(RegistryConstants.PATH_SEPARATOR) + 1); } return lifeCycleNameList; } } public static String getContextRoot() { if (contextRoot == null) { return RegistryConstants.LIFECYCLE_CONFIGURATION_PATH; } return contextRoot; } public static void setContextRoot(String contextRoot) { if (!contextRoot.endsWith(RegistryConstants.PATH_SEPARATOR)) contextRoot += RegistryConstants.PATH_SEPARATOR; CommonUtil.contextRoot = contextRoot; } /** * This method reads all the lifecycle configuration files from a folder and add the already added configurations * as aspects. * * @param registry tenant registry * @param rootRegistry root registry * @return * @throws RegistryException * @throws FileNotFoundException * @throws XMLStreamException */ public static boolean addDefaultLifecyclesIfNotAvailable(Registry registry, Registry rootRegistry) throws RegistryException, FileNotFoundException, XMLStreamException { if (!registry.resourceExists(RegistryConstants.LIFECYCLE_CONFIGURATION_PATH)) { Collection lifeCycleConfigurationCollection = new CollectionImpl(); registry.put(RegistryConstants.LIFECYCLE_CONFIGURATION_PATH, lifeCycleConfigurationCollection); String defaultLifecycleConfigLocation = getDefaltLifecycleConfigLocation(); File defaultLifecycleConfigDirectory = new File(defaultLifecycleConfigLocation); if (!defaultLifecycleConfigDirectory.exists()) { return false; } FilenameFilter filenameFilter = new FilenameFilter() { @Override public boolean accept(File file, String name) { return name.endsWith(".xml"); } }; File[] lifecycleConfigFiles = defaultLifecycleConfigDirectory.listFiles(filenameFilter); if (lifecycleConfigFiles != null && lifecycleConfigFiles.length == 0) { return false; } for (File lifecycleConfigFile : lifecycleConfigFiles) { String fileName = FilenameUtils.removeExtension(lifecycleConfigFile.getName()); //here configuration file name should be same as aspect name String resourcePath = RegistryConstants.LIFECYCLE_CONFIGURATION_PATH + fileName; String fileContent = null; //here we are checking whether the resource is already exists in registry. Otherwise we have to read all the //files and check if (!registry.resourceExists(resourcePath)) { try { fileContent = FileUtils.readFileToString(lifecycleConfigFile); } catch (IOException e) { String msg = String.format("Error while reading lifecycle config file %s ", fileName); log.error(msg, e); /* The exception is not thrown, because if we throw the error, the for loop will be broken and other files won't be read */ } if ((fileContent != null) && !fileContent.isEmpty()) { try { //here we are checking the file name and aspect name to enforce that, both are same OMElement omElement = buildOMElement(fileContent); String aspectName = omElement.getAttributeValue(new QName("name")); if (fileName.equalsIgnoreCase(aspectName)) { addLifecycle(fileContent, registry, rootRegistry); } else { String msg = String.format( "Configuration file name %s not matched with aspect name %s ", fileName, aspectName); log.error(msg); /* The error is not thrown, because if we throw the error, the for loop will be broken and other files won't be read */ } } catch (RegistryException e) { String msg = String.format("Error while adding aspect %s ", fileName); log.error(msg, e); /* The exception is not thrown, because if we throw the error, the for loop will be broken and other files won't be read */ } } } else { try { generateAspect(resourcePath, registry); } catch (Exception e) { String msg = String.format("Error while generating aspect %s ", fileName); log.error(msg, e); /* The exception is not thrown, because if we throw the error, the for loop will be broken and other aspects won't be added */ } } } } else { Resource lifecycleRoot = registry.get(getContextRoot()); if (!(lifecycleRoot instanceof Collection)) { String msg = "Failed to continue as the lifecycle configuration root: " + getContextRoot() + " is not a collection."; log.error(msg); throw new RegistryException(msg); } Collection lifecycleRootCol = (Collection) lifecycleRoot; String[] lifecycleConfigPaths = lifecycleRootCol.getChildren(); if (lifecycleConfigPaths != null) { for (String lifecycleConfigPath : lifecycleConfigPaths) { generateAspect(lifecycleConfigPath, registry); } } } return true; } public static String getDefaltLifecycleConfigLocation() { return System.getProperty(ServerConstants.CARBON_HOME) + File.separator + "repository" + File.separator + "resources" + File.separator + "lifecycles"; } public static boolean isLifecycleNameInUse(String name, Registry registry, Registry rootRegistry) throws RegistryException, XMLStreamException { if (name.contains("<aspect")) { OMElement element = AXIOMUtil.stringToOM(name); if (element != null) { name = element.getAttributeValue(new QName("name")); boolean aspectFound = false; String[] aspects = registry.getAvailableAspects(); if (aspects != null) { for (String aspect : aspects) { if (name.equals(aspect)) { return true; } } } return false; } else throw new RegistryException("Lifecycle Configuration does not contain the name attribute"); } String sql = null; // if (!registry.resourceExists(searchLCMPropertiesQuery)) { if (StaticConfiguration.isVersioningProperties()) { sql = "SELECT R.REG_PATH_ID, R.REG_NAME FROM REG_RESOURCE R , REG_PROPERTY PP, REG_RESOURCE_PROPERTY RP " + "WHERE R.REG_VERSION=RP.REG_VERSION AND " + "RP.REG_PROPERTY_ID=PP.REG_ID AND PP.REG_NAME=? AND PP.REG_VALUE=?"; } else { sql = "SELECT R.REG_PATH_ID, R.REG_NAME FROM REG_RESOURCE R, REG_PROPERTY PP, REG_RESOURCE_PROPERTY RP WHERE " + "R.REG_PATH_ID=RP.REG_PATH_ID AND " + "((R.REG_NAME=RP.REG_RESOURCE_NAME) OR (R.REG_NAME IS NULL AND RP.REG_RESOURCE_NAME IS NULL)) AND " + "RP.REG_PROPERTY_ID=PP.REG_ID AND " + "PP.REG_NAME=? AND PP.REG_VALUE=?"; } // This modification is done to stop the queries been stored to the registry. /*Resource q1 = registry.newResource(); q1.setContent(sql); q1.setMediaType(RegistryConstants.SQL_QUERY_MEDIA_TYPE); q1.addProperty(RegistryConstants.RESULT_TYPE_PROPERTY_NAME, RegistryConstants.RESOURCES_RESULT_TYPE); registry.put(searchLCMPropertiesQuery, q1);*/ // } Map<String, String> parameters = new HashMap<String, String>(); // if (sql != null && RegistryUtils.isRegistryReadOnly(registry.getRegistryContext())) { // parameters.put("query", sql); // } parameters.put("query", sql); parameters.put("1", "registry.LC.name"); parameters.put("2", name); // Collection result = rootRegistry.executeQuery(RegistryConstants.CONFIG_REGISTRY_BASE_PATH + // searchLCMPropertiesQuery, parameters); Collection result = rootRegistry.executeQuery(null, parameters); String[] servicePaths = result.getChildren(); if ((servicePaths == null) || (servicePaths.length == 0)) { return false; } return true; } // The methods have been duplicated in several places because there is no common bundle to place them. // We have to keep this inside different bundles so that users will not run in to problems if they uninstall some features public static boolean validateOMContent(OMElement omContent, Validator validator) { try { InputStream is = new ByteArrayInputStream(omContent.toString().getBytes("utf-8")); Source xmlFile = new StreamSource(is); if (validator != null) { validator.validate(xmlFile); } } catch (SAXException e) { log.error("Unable to parse the XML configuration. Please validate the XML configuration", e); return false; } catch (UnsupportedEncodingException e) { log.error("Unsupported content", e); return false; } catch (IOException e) { log.error("Unable to parse the XML configuration. Please validate the XML configuration", e); return false; } return true; } public static Validator getLifecycleSchemaValidator(String schemaPath) { if (lifecycleSchemaValidator == null) { try { SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); Schema schema = schemaFactory.newSchema(new File(schemaPath)); lifecycleSchemaValidator = schema.newValidator(); } catch (SAXException e) { log.error("Unable to get a schema validator from the given file path : " + schemaPath); } } return lifecycleSchemaValidator; } public static String getLifecycleSchemaLocation() { return CarbonUtils.getCarbonHome() + File.separator + "repository" + File.separator + "resources" + File.separator + "lifecycle-config.xsd"; } public static boolean validateSCXMLDataModel(OMElement content) { // fetch all state elements String stateXpath = "//x:state"; String forEventXpath = "//@forEvent"; String transitionXpath = "//x:transition"; List stateList = evaluateXpath(content, stateXpath, "x"); if (stateList != null) { for (Object stateObject : stateList) { OMElement state = ((OMElement) stateObject).cloneOMElement(); List<String> stateForEvents = new ArrayList<String>(); // Fetch all the transition Elements List transitions = evaluateXpath(state, transitionXpath, "x"); if (transitions != null) { for (Object transition : transitions) { OMElement transitionElement = (OMElement) transition; stateForEvents.add(transitionElement.getAttributeValue(new QName("event"))); } } // Fetch all the forEvent Elements List allForEvents = evaluateXpath(state, forEventXpath, null); if (allForEvents != null) { for (Object forEvent : allForEvents) { OMAttribute forEventElement = (OMAttribute) forEvent; if (!forEventElement.getAttributeValue().equals("")) { String[] forEvents = forEventElement.getAttributeValue().split(","); for (String event : forEvents) { if (!stateForEvents.contains(event)) { return false; } } } } } } } return true; } public static List evaluateXpath(OMElement contentElement, String xpathString, String nsPrefix) { List ret = new ArrayList(); try { AXIOMXPath xpath = new AXIOMXPath(xpathString); Iterator nsIterator = contentElement.getAllDeclaredNamespaces(); if (nsIterator.hasNext()) { while (nsIterator.hasNext()) { OMNamespace next = (OMNamespace) nsIterator.next(); xpath.addNamespace(nsPrefix, next.getNamespaceURI()); ret.addAll(xpath.selectNodes(contentElement)); } } else if (contentElement.getDefaultNamespace() != null) { xpath.addNamespace(nsPrefix, contentElement.getDefaultNamespace().getNamespaceURI()); ret.addAll(xpath.selectNodes(contentElement)); } else if (nsPrefix != null) { xpathString = xpathString.replace(nsPrefix + ":", ""); xpath = new AXIOMXPath(xpathString); ret.addAll(xpath.selectNodes(contentElement)); } else { xpath = new AXIOMXPath(xpathString); ret.addAll(xpath.selectNodes(contentElement)); } return ret; } catch (Exception e) { log.error(e); } return null; } public static void validateLifeCycle(OMElement element) throws RegistryException { String stateXpath = "//x:state"; String checkItems = "//x:data[@name='checkItems']"; // "//@forEvent"; String transitionValidation = "//x:data[@name='transitionValidation']"; String transitionPermission = "//x:data[@name='transitionPermission']"; String transitionScripts = "//x:data[@name='transitionScripts']"; String transitionExecution = "//x:data[@name='transitionExecution']"; String transitionUI = "//x:data[@name='transitionUI']"; String transitionApproval = "//x:data[@name='transitionApproval']"; List stateList = evaluateXpath(element, stateXpath, "x"); if (stateList != null) { for (Object stateObject : stateList) { OMElement state = ((OMElement) stateObject).cloneOMElement(); validateElements(state, checkItems, "item"); validateElements(state, transitionValidation, "validation"); validateElements(state, transitionPermission, "permission"); validateElements(state, transitionScripts, "js"); validateElements(state, transitionExecution, "execution"); validateElements(state, transitionUI, "ui"); validateElements(state, transitionApproval, "approval"); } } } private static void validateElements(OMElement element, String xpath, String childElement) throws RegistryException { List elements = evaluateXpath(element, xpath, "x"); if (elements != null) { for (Object object : elements) { OMElement cloneElement = ((OMElement) object).cloneOMElement(); Iterator children = cloneElement.getChildElements(); while (children.hasNext()) { String elementName = ""; Object node = children.next(); if (node instanceof OMText) { elementName = ((OMText) node).getText(); } else if (node instanceof OMElement) { elementName = ((OMElement) node).getLocalName(); } if (!elementName.equals(childElement)) { String message = "Unable to validate the lifecycle configuration"; log.error(message); throw new RegistryException(message); } } } } } }