/*
* 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;
}
}
}