/* * JBoss, Home of Professional Open Source. * Copyright 2008, Red Hat Middleware LLC, and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.deployment; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.StringTokenizer; import org.jboss.logging.Logger; /** * SuffixOrderHelper. * * This class wraps the SuffixOrder and EnhandedSuffixes attributes * of MainDeployer. * * @author <a href="mailto:dimitris@jboss.org">Dimitris Andreadis</a> * @version $Revision: 81033 $ */ public final class SuffixOrderHelper { // Constants ----------------------------------------------------- /** * Default EnhancedSuffixes * * Those values are indicative - we just know they'll work with * the compiled order of subdeployers like the aop or ejb3, * but any order can be set using the EnhancedSuffixes * attribute and/or the individual subdeployer's relative order. * * The commented out entries indicate those are dynamically * added by their respective subdeployers when they register. */ public static final String[] DEFAULT_ENHANCED_SUFFIXES = {}; /* Moved this list to org.jboss.deployment.MainDeployer-xmbean.xml so there are no hardcoded defaults. { //"050:.deployer", //"050:-deployer.xml", //"100:.aop", //"100:-aop.xml", //"150:.sar", //"150:-service.xml", //"200:.beans", "250:.rar", "300:-ds.xml", //"350:.har", "400:.jar", // ejb .jar //"450:.ejb3", //"450:.par", "500:.war", // don't comment out this! "600:.wsr", "650:.ear", //"700:.jar", // plain .jar //"750:.zip", "800:.bsh", "900:.last" // the JARDeployer really handles those? }; */ /** A default relative order just before 900:.last */ public static final int DEFAULT_RELATIVE_ORDER = 850; /** The Logger */ public static final Logger log = Logger.getLogger(SuffixOrderHelper.class); // Private Data -------------------------------------------------- /** Wrapped DeploymentSorter that stores the value for SuffixOrder attribute */ private final DeploymentSorter sorter; /** The actual value of EnhancedSuffixes attribute */ private String[] enhancedSuffixes; /** List of sorted EnhancedSuffix instances */ private List suffixes; /** Set of static String suffixes that cannot be overriden/removed */ private Set staticSuffixes; // Constructor --------------------------------------------------- public SuffixOrderHelper(DeploymentSorter sorter) { this.sorter = sorter; this.suffixes = new ArrayList(); this.staticSuffixes = new HashSet(); } // Accessors ----------------------------------------------------- /** * Getter only for the SuffixOrder as known by the MainDeployer and the Scanners * * The value is updated during init() with suffixes that remain constant. * After that suffixes are added/removed using the corresponding methods. * * @return the SuffixOrder string array */ public String[] getSuffixOrder() { return sorter.getSuffixOrder(); } /** * Getter for the EnhancedSuffixes attribute * * @return the EnhancedSuffixes string array */ public String[] getEnhancedSuffixes() { return enhancedSuffixes; } /** * Setter for the EnhancedSuffixes attribute * * @param enhancedSuffixes the EnhancedSuffixes string array */ public void setEnhancedSuffixes(String[] enhancedSuffixes) { this.enhancedSuffixes = enhancedSuffixes; } /** * Initialise the SuffixOrder from EnhancedSuffixes. * * If no enchangedSuffixes is specified, DEFAULT_ENHANCED_SUFFIXES * will be used. Individual entries may contain an additional order * element of the form [order:]suffix, e.g. 100:.sar * * The suffixes specified during init, will remain constant, * i.e. they can't be overriden or removed. */ public void initialize() { // if enhancedSuffixes not provided, use the default if (enhancedSuffixes == null) { enhancedSuffixes = DEFAULT_ENHANCED_SUFFIXES; } // reset, just in case we are called more than once suffixes.clear(); staticSuffixes.clear(); // add all enhanced suffixes; mark them as static, too. for (int i = 0; i < enhancedSuffixes.length; i++) { EnhancedSuffix es = new EnhancedSuffix(enhancedSuffixes[i]); addSuffix(es); // mark all initial entries as static! staticSuffixes.add(es.suffix); } // set the resulting SuffixOrder sorter.setSuffixOrder(produceSuffixOrder()); } /** * Add the specified enhanced suffixes in the correct * position(s) and regenerate the SuffixOrder, if needed. * * A suffix that exists already and is marked as static * will be skipped. Otherwise, duplicate entries are allowed. */ public void addEnhancedSuffixes(String [] enhancedSuffixes) { if (enhancedSuffixes != null) { // remember the initial size of the list int size = suffixes.size(); // add all enhanced suffixes for (int i = 0; i < enhancedSuffixes.length; i++) { EnhancedSuffix es = new EnhancedSuffix(enhancedSuffixes[i]); addSuffix(es); } if (suffixes.size() > size) { // suffixes were added, recreate the resulting SuffixOrder sorter.setSuffixOrder(produceSuffixOrder()); } } } /** * Insert the specified suffixes in the correct position * and regenerate the SuffixOrder array, if needed. * * A suffix that exists already and is marked as static * will be skipped. Otherwise, duplicate entries are allowed. */ public void addSuffixes(String[] suffixes, int relativeOrder) { if (suffixes != null) { // remember the initial size of the list int size = this.suffixes.size(); for (int i = 0; i < suffixes.length; i++) { addSuffix(new EnhancedSuffix(suffixes[i], relativeOrder)); } if (this.suffixes.size() > size) { // suffixes were added, recreate the resulting SuffixOrder sorter.setSuffixOrder(produceSuffixOrder()); } } } /** * Remove the enhanced suffixes if they are not marked as static * and regenerate the SuffixOrder, if needed. */ public void removeEnhancedSuffixes(String[] enhancedSuffixes) { if (enhancedSuffixes != null) { // remember the initial size of the list int size = suffixes.size(); for (int i = 0; i < enhancedSuffixes.length; i++) { EnhancedSuffix es = new EnhancedSuffix(enhancedSuffixes[i]); // if this is a static suffix, don't remove if (staticSuffixes.contains(es.suffix)) { continue; } else { // remove if exists suffixes.remove(es); } } if (this.suffixes.size() < size) { // entries removed, recreate the resulting SuffixOrder sorter.setSuffixOrder(produceSuffixOrder()); } } } /** * Remove the specified suffixes if they are not marked as static * and regenerate the SuffixOrder, if needed. */ public void removeSuffixes(String[] suffixes, int relativeOrder) { if (suffixes != null) { // remember the initial size of the list int size = this.suffixes.size(); for (int i = 0; i < suffixes.length; i++) { // if this is a static suffix, don't remove if (staticSuffixes.contains(suffixes[i])) { continue; } else { // remove if exists this.suffixes.remove(new EnhancedSuffix(suffixes[i], relativeOrder)); } } if (this.suffixes.size() < size) { // entries removed, recreate the resulting SuffixOrder sorter.setSuffixOrder(produceSuffixOrder()); } } } // Private ------------------------------------------------------- /** * Produce the SuffixOrder from the sorted suffixes ArrayList */ private String[] produceSuffixOrder() { String[] suffixOrder = new String[suffixes.size()]; for (int i = 0; i < suffixes.size(); i++) { suffixOrder[i] = ((EnhancedSuffix)suffixes.get(i)).suffix; } return suffixOrder; } /** * Add an EnhancedSuffix at the correct position in the sorted List. * * Sorting is based on EnhancedSuffix.order. A new entry with an equal * order value to an existing entry is placed AFTER the existing entry. * * If EnhancedSuffix.suffix exists in the staticSuffixes Set the entry * is NOT added. Otherwise, they EnhancedSuffix will be added, even * if it is a duplicate of an existing one. * * @param enhancedsuffix the enhanced suffix */ private void addSuffix(EnhancedSuffix enhancedSuffix) { // if this is a static suffix, don't add it if (staticSuffixes.contains(enhancedSuffix.suffix)) { log.debug("Static suffix exists; ignoring request for adding enhanced suffix: " + enhancedSuffix); } else { int size = suffixes.size(); // if List empty, just add the suffix if (size == 0) { suffixes.add(enhancedSuffix); } else { // insertion sort starting from the last element for (int i = size - 1; i > -1; i--) { EnhancedSuffix entry = (EnhancedSuffix)suffixes.get(i); if (enhancedSuffix.order >= entry.order) { // add the suffix AFTER the entry and stop suffixes.add(i + 1, enhancedSuffix); break; } else if (i == 0) { // reached the beginning so add the suffix right there suffixes.add(0, enhancedSuffix); } } } } } /** * Inner class that encapsulates an enhanceSuffix * consisting of suffix + order */ public final static class EnhancedSuffix { /** The suffix, e.g. .sar */ public String suffix; /** The order, by convention a 3 digit number, e.g. 100 */ public int order; /** * Simple CTOR */ public EnhancedSuffix(String suffix, int order) { this.suffix = suffix; this.order = order; } /** * CTOR that parses an enhancedSuffix string of the form: [order:]suffix * If the optional 'order' is missing, use DEFAULT_RELATIVE_ORDER */ public EnhancedSuffix(String enhancedSuffix) throws IllegalArgumentException { StringTokenizer tokenizer = new StringTokenizer(enhancedSuffix, ":"); int tokens = tokenizer.countTokens(); switch (tokens) { case 1: this.order = DEFAULT_RELATIVE_ORDER; this.suffix = enhancedSuffix; break; case 2: this.order = Integer.parseInt(tokenizer.nextToken()); this.suffix = tokenizer.nextToken(); break; default: throw new IllegalArgumentException("Cannot parse enhancedSuffix: " + enhancedSuffix); } } /** * Override equals to allow EnhancedSuffix to be searchable * using ArrayList.indexOf()/ArrayList.lastIndexOf() * * Base equality on both suffix and order */ public boolean equals(Object other) { if (other == this) return true; if (!(other instanceof EnhancedSuffix)) return false; EnhancedSuffix that = (EnhancedSuffix)other; // suffix shouldn't be null return this.suffix.equals(that.suffix) && this.order == that.order; } /** * Use both fields */ public int hashCode() { int result = 17; result = 37 * result + suffix.hashCode(); result = 37 * result + order; return result; } /** * Pretty print */ public String toString() { return order + ":" + suffix; } } }