/* * Copyright 2014 Red Hat, Inc. and/or its affiliates. * * 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.drools.workbench.jcr2vfsmigration.jcrExport; import java.io.FileNotFoundException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Comparator; import java.util.List; import javax.inject.Inject; import com.google.gwt.user.client.rpc.SerializationException; import org.apache.commons.lang3.StringUtils; import org.drools.guvnor.client.common.AssetFormats; import org.drools.guvnor.client.rpc.AssetPageRequest; import org.drools.guvnor.client.rpc.AssetPageRow; import org.drools.guvnor.client.rpc.Module; import org.drools.guvnor.client.rpc.PageResponse; import org.drools.guvnor.client.rpc.TableDataResult; import org.drools.guvnor.client.rpc.TableDataRow; import org.drools.guvnor.server.RepositoryAssetService; import org.drools.guvnor.server.RepositoryModuleService; import org.drools.guvnor.server.repository.Preferred; import org.drools.repository.AssetItem; import org.drools.repository.ModuleItem; import org.drools.repository.ModuleIterator; import org.drools.repository.RulesRepository; import org.drools.workbench.jcr2vfsmigration.common.FileManager; import org.drools.workbench.jcr2vfsmigration.jcrExport.asset.AttachmentAssetExporter; import org.drools.workbench.jcr2vfsmigration.jcrExport.asset.ExportContext; import org.drools.workbench.jcr2vfsmigration.jcrExport.asset.FactModelExporter; import org.drools.workbench.jcr2vfsmigration.jcrExport.asset.GuidedDecisionTableExporter; import org.drools.workbench.jcr2vfsmigration.jcrExport.asset.GuidedEditorExporter; import org.drools.workbench.jcr2vfsmigration.jcrExport.asset.PlainTextAssetExporter; import org.drools.workbench.jcr2vfsmigration.jcrExport.asset.PlainTextAssetWithPackagePropertyExporter; import org.drools.workbench.jcr2vfsmigration.util.ExportUtils; import org.drools.workbench.jcr2vfsmigration.xml.format.ModulesXmlFormat; import org.drools.workbench.jcr2vfsmigration.xml.format.XmlAssetsFormat; import org.drools.workbench.jcr2vfsmigration.xml.model.ModuleType; import org.drools.workbench.jcr2vfsmigration.xml.model.Modules; import org.drools.workbench.jcr2vfsmigration.xml.model.asset.IgnoredAsset; import org.drools.workbench.jcr2vfsmigration.xml.model.asset.XmlAsset; import org.drools.workbench.jcr2vfsmigration.xml.model.asset.XmlAssets; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ModuleAssetExporter { private static final Logger logger = LoggerFactory.getLogger(ModuleAssetExporter.class); private static int assetFileName = 1; private static final String GLOBAL_KEYWORD = "global "; @Inject private FileManager fileManager; @Inject private ExportUtils exportUtils; @Inject private RepositoryModuleService jcrRepositoryModuleService; @Inject private RepositoryAssetService jcrRepositoryAssetService; @Inject @Preferred private RulesRepository rulesRepository; @Inject private PlainTextAssetExporter plainTextAssetExporter; @Inject private PlainTextAssetWithPackagePropertyExporter plainTextAssetWithPackagePropertyExporter; @Inject private GuidedEditorExporter guidedEditorExporter; @Inject private GuidedDecisionTableExporter guidedDecisionTableExporter; @Inject private FactModelExporter factModelExporter; @Inject private AttachmentAssetExporter attachmentAssetExporter; private ModulesXmlFormat modulesXmlFormat = new ModulesXmlFormat(); private XmlAssetsFormat xmlAssetsFormat = new XmlAssetsFormat(); public void exportAll() { logger.info( " Module export started" ); Module jcrGlobalModule = jcrRepositoryModuleService.loadGlobalModule(); Module[] jcrModules = jcrRepositoryModuleService.listModules(); if ( jcrGlobalModule == null && jcrModules.length == 0 ) { logger.info( " No modules to be exported" ); return; } Collection<org.drools.workbench.jcr2vfsmigration.xml.model.Module> normalModules = new ArrayList<org.drools.workbench.jcr2vfsmigration.xml.model.Module>( 5 ); for ( Module jcrModule : jcrModules ) { normalModules.add( export( ModuleType.NORMAL, jcrModule ) ); } org.drools.workbench.jcr2vfsmigration.xml.model.Module globalModule = export( ModuleType.GLOBAL, jcrGlobalModule ); Modules modules = new Modules( globalModule, normalModules ); StringBuilder xml = new StringBuilder(); modulesXmlFormat.format( xml, modules ); PrintWriter pw = fileManager.createModuleExportFileWriter(); pw.print( xml.toString() ); pw.close(); logger.info( " Module export ended" ); } private org.drools.workbench.jcr2vfsmigration.xml.model.Module export( ModuleType moduleType, Module jcrModule ) { logger.info( " Exporting module [{}] (UUID={}).", jcrModule.getName(), jcrModule.getUuid() ); //setting CategoryRules to jcr module (needed in asset migration) for( ModuleIterator packageItems = rulesRepository.listModules(); packageItems.hasNext(); ) { ModuleItem packageItem = packageItems.next(); if( packageItem.getUUID().equals( jcrModule.getUuid() ) ){ jcrModule.setCatRules( packageItem.getCategoryRules() ); break; } } // Save module name for later String moduleName = jcrModule.getName(); String normalizedPackageName = exportUtils.normalizePackageName( jcrModule.getName() ); jcrModule.setName( normalizedPackageName ); // Export package header info String packageHeaderInfo = null; try { List<String> formats = new ArrayList<String>(); formats.add("package"); AssetPageRequest request = new AssetPageRequest(jcrModule.getUuid(), formats, null, 0, 10); PageResponse<AssetPageRow> response = jcrRepositoryAssetService.findAssetPage(request); if (response.getTotalRowSize() > 0) { AssetPageRow row = response.getPageRowList().get(0); AssetItem assetItemJCR = rulesRepository.loadAssetByUUID(row.getUuid()); packageHeaderInfo = assetItemJCR.getContent(); } } catch ( SerializationException e ) { throw new IllegalStateException( e ); } // Export globalsString StringBuffer sbGlobal = new StringBuffer(); List<String> lGlobals = ExportUtils.parseGlobals( packageHeaderInfo ); if (lGlobals.size() > 0) { for(String global : lGlobals) { sbGlobal.append(GLOBAL_KEYWORD); sbGlobal.append(global); sbGlobal.append("\n"); } } String assetExportFileName = setupAssetExportFile( jcrModule.getUuid() ); boolean assetExportSuccess = exportModuleAssets( jcrModule, assetExportFileName ); if ( !assetExportSuccess ) logger.error( "An error occurred during asset export for module {} (UUID={})!", jcrModule.getName(), jcrModule.getUuid() ); return new org.drools.workbench.jcr2vfsmigration.xml.model.Module( moduleType, jcrModule.getUuid(), moduleName, jcrModule.getLastContributor(), jcrModule.getCheckinComment(), jcrModule.getLastModified(), normalizedPackageName, packageHeaderInfo, sbGlobal.toString(), jcrModule.getCatRules(), assetExportFileName ); } private boolean exportModuleAssets( Module jcrModule, String assetFileName ) { Collection<XmlAsset> assets = new ArrayList<XmlAsset>( 10 ); StringBuilder xml = new StringBuilder(); PrintWriter pw; try { pw = fileManager.createAssetExportFileWriter( assetFileName ); } catch ( FileNotFoundException e ) { logger.error("Can't find file for {}!", assetFileName, e); return false; } boolean hasMorePages = true; int startRowIndex = 0; final int pageSize = 100; PageResponse<AssetPageRow> response; while (hasMorePages) { AssetPageRequest request = new AssetPageRequest(jcrModule.getUuid(), null, // get all formats null, startRowIndex, pageSize); String assetName=""; try { response = jcrRepositoryAssetService.findAssetPage(request); for (AssetPageRow row : response.getPageRowList()) { AssetItem assetItemJCR = rulesRepository.loadAssetByUUID( row.getUuid() ); assetName = assetItemJCR.getName(); boolean isDisabled = assetItemJCR.getDisabled(); if ( isDisabled ) { logger.info(" Ignoring disabled asset [{}.{}].", assetItemJCR.getName(), assetItemJCR.getFormat()); } else { logger.info(" Exporting asset [{}.{}].", assetItemJCR.getName(), assetItemJCR.getFormat()); //TODO: Git won't check in a version if the file is not changed in this version. Eg, the version 3 of "testFunction.function" //We need to find a way to force a git check in. Otherwise migrated version history is not consistent with the version history in old Guvnor. //Still need to migrate the "current version" even though in most cases the "current version" (actually it is not a version in version //control, its just the current content on jcr node) is equal to the latest version that had been checked in. //Eg, when we import mortgage example, we just dump the mortgage package to a jcr node, no version check in. XmlAsset xmlAsset = export( ExportContext.create( jcrModule, assetItemJCR, assetFileName ) ); xmlAsset.setAssetHistory( exportAssetHistory( ExportContext.create( jcrModule, row.getUuid(), assetFileName ) ) ); assets.add( xmlAsset ); } } } catch (SerializationException e) { logger.error("SerializationException exporting asset {} from module {}!", assetName, jcrModule.getName(), e); return false; } catch (Exception e) { logger.error("Exception exporting asset {} from module {}!", assetName, jcrModule.getName(), e); return false; } if (response.isLastPage()) { hasMorePages = false; } else { startRowIndex += pageSize; } } xmlAssetsFormat.format( xml, new XmlAssets( assets ) ); pw.print( xml.toString() ); pw.close(); return true; } private XmlAsset export( ExportContext exportContext ) { String name = exportContext.getJcrAssetItem().getName(); String format = exportContext.getJcrAssetItem().getFormat(); if ( AssetFormats.DRL_MODEL.equals( format ) ) { return factModelExporter.export( exportContext ); } else if (AssetFormats.BUSINESS_RULE.equals( format )) { return guidedEditorExporter.export( exportContext ); } else if (AssetFormats.DECISION_TABLE_GUIDED.equals( format )) { return guidedDecisionTableExporter.export( exportContext ); } else if (AssetFormats.ENUMERATION.equals( format ) || AssetFormats.DSL.equals( format ) || AssetFormats.DSL_TEMPLATE_RULE.equals( format ) || AssetFormats.RULE_TEMPLATE.equals( format ) || AssetFormats.FORM_DEFINITION.equals( format ) || AssetFormats.SPRING_CONTEXT.equals( format ) || AssetFormats.SERVICE_CONFIG.equals( format ) || AssetFormats.WORKITEM_DEFINITION.equals( format ) || AssetFormats.CHANGE_SET.equals( format ) || AssetFormats.RULE_FLOW_RF.equals( format ) || AssetFormats.BPMN_PROCESS.equals( format ) || AssetFormats.BPMN2_PROCESS.equals( format ) || "ftl".equals( format ) || "json".equals( format ) || "fw".equals( format )) { return plainTextAssetExporter.export( exportContext ); } else if (AssetFormats.DRL.equals( format ) || AssetFormats.FUNCTION.equals( format )) { return plainTextAssetWithPackagePropertyExporter.export( exportContext ); } else if (AssetFormats.DECISION_SPREADSHEET_XLS.equals( format ) || AssetFormats.SCORECARD_SPREADSHEET_XLS.equals( format ) || "png".equals( format ) || "gif".equals( format ) || "jpg".equals( format ) || "pdf".equals( format ) || "doc".equals( format ) || "odt".equals( format )) { return attachmentAssetExporter.export( exportContext ); } else if (AssetFormats.MODEL.equals( format )) { logger.warn(" POJO Model jar [{}] is not supported by export tool. Please add your POJO model jar to Guvnor manually.", name); return new IgnoredAsset(); } else if (AssetFormats.SCORECARD_GUIDED.equals( format )) { // No special treatment or attributes needed; use PlainTextAsset return plainTextAssetExporter.export( exportContext ); } else if (AssetFormats.TEST_SCENARIO.equals( format )) { // No special treatment or attributes needed; use PlainTextAsset return plainTextAssetExporter.export( exportContext ); } else if ("package".equals( format )) { return new IgnoredAsset(); } else { //another format is migrated as a attachmentAsset logger.warn(" Asset [{}.{}] is not a known format by export tool. It will be exported as attachmentAsset", name, format ); return attachmentAssetExporter.export( exportContext ); } } private XmlAssets exportAssetHistory( ExportContext historyContext ) throws SerializationException { XmlAssets xmlAssets = new XmlAssets(); //loadItemHistory wont return the current version String currentVersionAssetName=""; try { TableDataResult history = jcrRepositoryAssetService.loadItemHistory( historyContext.getAssetUUID() ); TableDataRow[] rows = history.data; Arrays.sort( rows, new Comparator<TableDataRow>() { public int compare( TableDataRow r1, TableDataRow r2 ) { Integer v2 = Integer.valueOf( r2.values[ 0 ] ); Integer v1 = Integer.valueOf( r1.values[ 0 ] ); return v1.compareTo( v2 ); } } ); String historicalAssetExportFileName = "h_" + historyContext.getAssetExportFileName(); for (TableDataRow row : rows) { AssetItem historicalAssetJCR = rulesRepository.loadAssetByUUID( row.id ); currentVersionAssetName = historicalAssetJCR.getName(); ExportContext historicalAssetExportContext = ExportContext.create( historyContext.getJcrModule(), historicalAssetJCR, historicalAssetExportFileName ); xmlAssets.addAsset( export( historicalAssetExportContext ) ); logger.info( " Asset [{}.{}] migrated: version [{}], comment [{}], lastModified [{}]", historicalAssetJCR.getName(), historicalAssetJCR.getFormat(), historicalAssetJCR.getVersionNumber(), historicalAssetJCR.getCheckinComment(), historicalAssetJCR.getLastModified().getTime() ); } } catch ( RuntimeException e ){ logger.error( "Exception migrating assetHistory at version {} from module {}!", currentVersionAssetName, historyContext.getJcrModule().getName() ); } return xmlAssets; } // Attempt creation of the asset export file firstly with the module's uuid. If this were null or the file could not // be successfully created, then try again with a shorter (i.e. simple number) name. private String setupAssetExportFile( String moduleUuid ) { StringBuilder fileNameBuilder = new StringBuilder(); boolean success = false; if ( StringUtils.isNotBlank( moduleUuid ) ) { fileNameBuilder.insert( 0, moduleUuid ); success = fileManager.createAssetExportFile( fileNameBuilder.toString() ); } if ( !success ) { fileNameBuilder.replace( 0, fileNameBuilder.lastIndexOf( "." ), Integer.toString( assetFileName++ ) ); success = fileManager.createAssetExportFile( fileNameBuilder.toString() ); if ( ! success ) { logger.error( "Module asset file could not be created" ); return null; } } return fileNameBuilder.toString(); } }