/** * Copyright 2010 JBoss Inc * * 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.guvnor.server.repository; import javax.jcr.RepositoryException; import org.drools.guvnor.client.common.AssetFormats; import org.drools.repository.AssetItem; import org.drools.repository.AssetItemIterator; import org.drools.repository.PackageItem; import org.drools.repository.PackageIterator; import org.drools.repository.RulesRepository; import org.jbpm.compiler.xml.processes.RuleFlowMigrator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This class is used to migrate version 4 ruleflow assets in a version 4 * or 5 drools repository into version 5 ruleflow assets. * IMPORTANT: the current code only performs the transformations if the * Drools system property drools.ruleflow.port is true, just as the * drools compiler only transforms version 4 ruleflows to 5 if this * property is set. * * If a ruleflow is migrated, it is checked in as new version so that * the previous version is preserved. The current code checks-in * the new version as the admin user with an appropriate comment indicating * that the flow has been migrated. Hover, the code could also be changed * to check-in each migrated ruleflow using the credentials of the last * person to check-in the ruleflow, however, in future there may be a * danger that the person who last checked in the file may have lost * privileges to check-in the file, so we use the admin user * for now. * * @author Shahad Ahmed */ public class MigrateRepository { private static final Logger log = LoggerFactory.getLogger( MigrateRepository.class ); /************************************************************************* * Returns true if the drools system property drools.ruleflow.port is true * indicating that ruleflow migration should be performed. * @param repo * @return true if the drools system property drools.ruleflow.port is true * indicating that ruleflow migration should be performed. * @throws RepositoryException ************************************************************************/ public static boolean needsRuleflowMigration(RulesRepository repo) throws RepositoryException { String portRuleFlow = System.getProperty( "drools.ruleflow.port", "false" ); return portRuleFlow.equalsIgnoreCase("true"); } /************************************************************************* * Iterates through all the packages in the given repository * migrating all drools 4 .rfm and .rf ruleflow assets that need to be * migrated to 5. * Note that archived assets, and assets in snapshots are also migrated. * @param repo * @throws RepositoryException ************************************************************************/ public static void migrateRuleflows(RulesRepository repo) throws RepositoryException { log.debug("AUTO MIGRATION: Performing drools ruleflow migration..."); PackageIterator pkgs = repo.listPackages(); boolean performed = false; while(pkgs.hasNext()) { performed = true; PackageItem pkg = (PackageItem) pkgs.next(); migrateRuleflows(pkg); String[] snaps = repo.listPackageSnapshots(pkg.getName()); if (snaps != null) { for (int i = 0; i < snaps.length; i++) { PackageItem snap = repo.loadPackageSnapshot(pkg.getName(), snaps[i]); migrateRuleflows(snap); } } } if (performed) { log.debug("AUTO MIGRATION: Drools rulesflow migration completed."); } } /************************************************************************* * migrate all ruleflows in the package, including archived ones. * The migrated ruleflow is checked in as a new version and previous * versions are not migrated. * NOTE that we always try to migrate if the drools.ruleflow.port * property is true, even if the repository has been migrated before. * This is needed as the drools.ruleflow.port property may have been * false when the repository was first migrated (i.e. the * HEADER_PROPERTY_NAME above may have been migrated, but not the * ruleflows). * Also, all snapshot packages are updated as well. * @param pkg ************************************************************************/ private static void migrateRuleflows(PackageItem pkg) { String portRuleFlow = System.getProperty( "drools.ruleflow.port", "false" ); if ( portRuleFlow.equalsIgnoreCase( "true" ) ) { AssetItemIterator it = listAssetsByFormatIncludingArchived(pkg, new String[]{AssetFormats.RULE_FLOW_RF}); while(it.hasNext()) { AssetItem item = it.next(); String rf = item.getContent(); try { if(RuleFlowMigrator.needToMigrateRFM(rf)) { log.debug("Migrating v4 RFM to v5: " + item.getName()); rf = RuleFlowMigrator.portRFMToCurrentVersion(rf); item.updateContent(rf); item.checkin("Auto migration from ruleflow RFM version 4 to 5"); } else if(RuleFlowMigrator.needToMigrateRF(rf)) { log.debug("Migrating v4 RF to v5: " + item.getName()); rf = RuleFlowMigrator.portRFToCurrentVersion(rf); item.updateContent(rf); item.checkin("Auto migration from ruleflow RF version 4 to 5"); } } catch (Exception ex) { log.error("Ruleflow migration failed for item: " + item.getName() + " due to " + ex); ex.printStackTrace(System.out); } } } } /************************************************************************* * This will load an iterator for assets in the given package of the * given format type, including archived assets. * @param pkg The package to check * @param formats an array of the format types to find. * @return an iterator for assets of the given format type, including * archived assets. ************************************************************************/ private static AssetItemIterator listAssetsByFormatIncludingArchived(PackageItem pkg, String[] formats) { if (formats.length == 1) { return pkg.queryAssets( "drools:format='" + formats[0] + "'" , true); } else { String predicate = " ( "; for ( int i = 0; i < formats.length; i++ ) { predicate = predicate + "drools:format='" + formats[i] + "'"; if (!(i == formats.length -1 )) { predicate = predicate + " OR "; } } predicate = predicate + " ) "; return pkg.queryAssets( predicate , true); } } }