/*
 * JBoss, Home of Professional Open Source
 * Copyright 2015, Red Hat, Inc., and individual contributors as indicated
 * by the @authors tag.
 *
 * 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.
 */

// DOMCatalogReader.java - Read XML Catalog files

package org.jboss.util.xml.catalog.readers;

import java.util.Hashtable;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;

import org.jboss.util.xml.catalog.Catalog;
import org.jboss.util.xml.catalog.CatalogException;
import org.jboss.util.xml.catalog.helpers.Namespaces;
import org.jboss.util.xml.catalog.readers.CatalogReader;

import org.xml.sax.SAXException;
import org.w3c.dom.*;

/**
 * A DOM-based CatalogReader.
 *
 *
This class is used to read XML Catalogs using the DOM. This reader
 * has an advantage over the SAX-based reader that it can analyze the
 * DOM tree rather than simply a series of SAX events. It has the disadvantage
 * that it requires all of the code necessary to build and walk a DOM
 * tree.

 *
 *
Since the choice of CatalogReaders (in the InputStream case) can only
 * be made on the basis of MIME type, the following problem occurs: only
 * one CatalogReader can exist for all XML mime types. In order to get
 * around this problem, the DOMCatalogReader relies on a set of external
 * CatalogParsers to actually build the catalog.

 *
 *
The selection of CatalogParsers is made on the basis of the QName
 * of the root element of the document.

 *
 *
This class requires the Java API for XML Parsing.

 *
 * @see Catalog
 * @see CatalogReader
 * @see SAXCatalogReader
 * @see TextCatalogReader
 * @see DOMCatalogParser
 *
 * @author Norman Walsh
 * Norman.Walsh@Sun.COM
 *
 * @version 1.0
 */
@SuppressWarnings("unchecked")
public class DOMCatalogReader implements CatalogReader {
  /**
   * Mapping table from QNames to CatalogParser classes.
   *
   *
Each key in this hash table has the form "elementname"
   * or "{namespaceuri}elementname". The former is used if the
   * namespace URI is null.

   */
  protected Hashtable namespaceMap = new Hashtable();

  /**
   * Add a new parser to the reader.
   *
   *
This method associates the specified parserClass with the
   * namespaceURI/rootElement names specified.

   *
   * @param namespaceURI The namespace URI. Not the prefix.
   * @param rootElement The name of the root element.
   * @param parserClass The name of the parserClass to instantiate
   * for this kind of catalog.
   */
  public void setCatalogParser(String namespaceURI,
			       String rootElement,
			       String parserClass) {
    if (namespaceURI == null) {
      namespaceMap.put(rootElement, parserClass);
    } else {
      namespaceMap.put("{"+namespaceURI+"}"+rootElement, parserClass);
    }
  }

  /**
   * Get the name of the parser class for a given catalog type.
   *
   *
This method returns the parserClass associated with the
   * namespaceURI/rootElement names specified.

   *
   * @param namespaceURI The namespace URI. Not the prefix.
   * @param rootElement The name of the root element.
   * @return The parser class.
   */
  public String getCatalogParser(String namespaceURI,
				 String rootElement) {
    if (namespaceURI == null) {
      return (String) namespaceMap.get(rootElement);
    } else {
      return (String) namespaceMap.get("{"+namespaceURI+"}"+rootElement);
    }
  }

  /**
   * Null constructor; something for subclasses to call.
   */
  public DOMCatalogReader() { }

  /**
   * Read a catalog from an input stream.
   *
   *
This class reads a catalog from an input stream:

   *
   *

   *
Based on the QName of the root element, it determines which
   * parser to instantiate for this catalog.

   *
It constructs a DOM Document from the catalog and

   *
For each child of the root node, it calls the parser's
   * parseCatalogEntry method. This method is expected to make
   * appropriate calls back into the catalog to add entries for the
   * entries in the catalog. It is free to do this in whatever manner
   * is appropriate (perhaps using just the node passed in, perhaps
   * wandering arbitrarily throughout the tree).

   *

   *
   * @param catalog The catalog for which this reader is called.
   * @param is The input stream that is to be read.
   * @throws IOException if the URL cannot be read.
   * (For example, if it is supposed to be XML and isn't well-formed or
   * if the parser class cannot be instantiated.)
   */
  public void readCatalog(Catalog catalog, InputStream is)
    throws IOException, CatalogException {

    DocumentBuilderFactory factory = null;
    DocumentBuilder builder = null;

    factory = DocumentBuilderFactory.newInstance();
    factory.setNamespaceAware(false);
    factory.setValidating(false);
    try {
      builder = factory.newDocumentBuilder();
    } catch (ParserConfigurationException pce) {
      throw new CatalogException(CatalogException.UNPARSEABLE);
    }

    Document doc = null;

    try {
      doc = builder.parse(is);
    } catch (SAXException se) {
      throw new CatalogException(CatalogException.UNKNOWN_FORMAT);
    }

    Element root = doc.getDocumentElement();

    String namespaceURI = Namespaces.getNamespaceURI(root);
    String localName    = Namespaces.getLocalName(root);

    String domParserClass = getCatalogParser(namespaceURI,
					     localName);

    if (domParserClass == null) {
      if (namespaceURI == null) {
	catalog.getCatalogManager().debug.message(1, "No Catalog parser for "
						  + localName);
      } else {
	catalog.getCatalogManager().debug.message(1, "No Catalog parser for "
						  + "{" + namespaceURI + "}"
						  + localName);
      }
      return;
    }

    DOMCatalogParser domParser = null;

    try {
      domParser = (DOMCatalogParser) Class.forName(domParserClass).newInstance();
    } catch (ClassNotFoundException cnfe) {
      catalog.getCatalogManager().debug.message(1, "Cannot load XML Catalog Parser class", domParserClass);
      throw new CatalogException(CatalogException.UNPARSEABLE);
    } catch (InstantiationException ie) {
      catalog.getCatalogManager().debug.message(1, "Cannot instantiate XML Catalog Parser class", domParserClass);
      throw new CatalogException(CatalogException.UNPARSEABLE);
    } catch (IllegalAccessException iae) {
      catalog.getCatalogManager().debug.message(1, "Cannot access XML Catalog Parser class", domParserClass);
      throw new CatalogException(CatalogException.UNPARSEABLE);
    } catch (ClassCastException cce ) {
      catalog.getCatalogManager().debug.message(1, "Cannot cast XML Catalog Parser class", domParserClass);
      throw new CatalogException(CatalogException.UNPARSEABLE);
    }

    Node node = root.getFirstChild();
    while (node != null) {
      domParser.parseCatalogEntry(catalog, node);
      node = node.getNextSibling();
    }
  }

  /**
   * Read the catalog behind the specified URL.
   *
   * @see #readCatalog(Catalog, InputStream)
   *
   * @param catalog The catalog for which we are reading.
   * @param fileUrl The URL of the document that should be read.
   *
   * @throws MalformedURLException if the specified URL cannot be
   * turned into a URL object.
   * @throws IOException if the URL cannot be read.
   */
  public void readCatalog(Catalog catalog, String fileUrl)
    throws MalformedURLException, IOException, CatalogException {
    URL url = new URL(fileUrl);
    URLConnection urlCon = url.openConnection();
    readCatalog(catalog, urlCon.getInputStream());
  }
}


/*
 * JBoss, Home of Professional Open Source
 * Copyright 2015, Red Hat, Inc., and individual contributors as indicated
 * by the @authors tag.
 *
 * 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.jboss.util.id;

import java.net.InetAddress;

import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Arrays;

import org.jboss.util.HashCode;
import org.jboss.util.platform.PID;

/**
 * An object that uniquely identifies a virtual machine.
 *
 *
The identifier is composed of:
 *

 *
The Internet address of the physical machine.

 *
The process identifier of the virtual machine.

 *
A UID to guarantee uniqness across multipule virtual
 *        machines on the same physical machine.

 *

 *
 *

 *    [ address ] - [ process id ] - [ time ] - [ counter ]
 *                                   |------- UID --------|
 *

 *
 *
Numbers are converted to radix(Character.MAX_RADIX) when converting
 *    to strings.
 *
 * @see UID
 *
 * @version <tt>$Revision$</tt>
 * @author  Jason Dillon
 */
@SuppressWarnings("unchecked")
public class VMID
   implements ID
{
   /** The serialVersionUID */
   private static final long serialVersionUID = -4339675822939194520L;
   /** The address of the current virtual machine */
   protected final byte[] address;

   /** The process identifier of the current virtual machine */
   protected final PID pid;

   /** A unique identifier to ensure uniqueness across the host machine */
   protected final UID uid;

   /** The hash code of this VMID */
   protected final int hashCode;

   /**
    * Construct a new VMID.
    *
    * @param address    The address of the current virtual machine.
    * @param pid        Process identifier.
    * @param uid        Unique identifier.
    *
    * @see #getInstance()  For getting a VMID instance reference.
    */
   protected VMID(final byte[] address, final PID pid, final UID uid) {
      this.address = address;
      this.pid = pid;
      this.uid = uid;

      // generate a hashCode for this VMID
      int code = pid.hashCode();
      code ^= uid.hashCode();
      code ^= HashCode.generate(address);
      hashCode = code;
   }

   /**
    * Copy a VMID.
    *
    * @param vmid    VMID to copy.
    */
   protected VMID(final VMID vmid) {
      this.address = vmid.address;
      this.pid = vmid.pid;
      this.uid = vmid.uid;
      this.hashCode = vmid.hashCode;
   }

   /**
    * Get the address portion of this VMID.
    *
    * @return  The address portion of this VMID.
    */
   public final byte[] getAddress() {
      return address;
   }

   /**
    * Get the process identifier portion of this VMID.
    *
    * @return  The process identifier portion of this VMID.
    */
   public final PID getProcessID() {
      return pid;
   }

   /**
    * Get the UID portion of this VMID.
    *
    * @return  The UID portion of this VMID.
    */
   public final UID getUID() {
      return uid;
   }

   /**
    * Return a string representation of this VMID.
    *
    * @return  A string representation of this VMID.
    */
   public String toString() {
      StringBuffer buff = new StringBuffer();

      for (int i=0; i<address.length; i++) {
         int n = (address[i] & 0xFF);
         buff.append(Integer.toString(n, Character.MAX_RADIX));
      }

      buff.append("-").append(pid.toString(Character.MAX_RADIX));
      buff.append("-").append(uid);

      return buff.toString();
   }

   /**
    * Return the hash code of this VMID.
    *
    * @return  The hash code of this VMID.
    */
   public final int hashCode() {
      return hashCode;
   }

   /**
    * Check if the given object is equal to this VMID.
    *
    *
A VMID is equals to another VMID if the address,
    *    process identifer and UID portions are equal.
    *
    * @param obj     Object to test equality with.
    * @return        True if object is equals to this VMID.
    */
   public boolean equals(final Object obj) {
      if (obj == this) return true;

      if (obj != null && obj.getClass() == getClass()) {
         VMID vmid = (VMID)obj;
         return
            Arrays.equals(vmid.address, address) &&
            vmid.pid.equals(pid) &&
            vmid.uid.equals(uid);
      }

      return false;
   }

   /**
    * Returns a copy of this VMID.
    *
    * @return  A copy of this VMID.
    */
   public Object clone() {
      try {
         return super.clone();
      }
      catch (CloneNotSupportedException e) {
         throw new InternalError();
      }
   }

   /**
    * Returns a VMID as a string.
    *
    * @return  VMID as a string.
    */
   public static String asString() {
      return getInstance().toString();
   }

   /////////////////////////////////////////////////////////////////////////
   //                            Instance Access                          //
   /////////////////////////////////////////////////////////////////////////

   /** The single instance of VMID for the running Virtual Machine */
   private static VMID instance = null;

   /**
    * Get the VMID for the current virtual machine.
    *
    * @return  Virtual machine identifier.
    *
    */
   public synchronized static VMID getInstance() {
      if (instance == null) {
         instance = create();
      }
      return instance;
   }

   /**
    * The address used when conventional methods fail to return the address
    * of the current machine.
    */
   public static final byte[] UNKNOWN_HOST = { 0, 0, 0, 0 };

   /**
    * Return the current host internet address.
    */
   private static byte[] getHostAddress() {
      return (byte[]) AccessController.doPrivileged(new PrivilegedAction() {
            public Object run() {
               try {
                  return InetAddress.getLocalHost().getAddress();
               }
               catch (Exception e) {
                  return UNKNOWN_HOST;
               }
            }
         });
   }

   /**
    * Create the VMID for the current virtual mahcine.
    *
    * @return  Virtual machine identifer.
    */
   private static VMID create() {
      // get the local internet address for the current host
      byte[] address = getHostAddress();

      return new VMID(address, PID.getInstance(), new UID());
   }
}


/*
 * JBoss, Home of Professional Open Source
 * Copyright 2015, Red Hat, Inc., and individual contributors as indicated
 * by the @authors tag.
 *
 * 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.jboss.util.xml;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;

import org.jboss.logging.Logger;
import org.jboss.util.xml.catalog.CatalogManager;
import org.jboss.util.xml.catalog.Resolver;
import org.xml.sax.InputSource;

/**
 *
 * A ThreadSpecificCatalogs class maintains all catalogfiles catolog.xml found in the
 * Thread.currentThread().getContextClassLoader().
 *
 * @author Daniel Wiese
 * @version $Revision$
 */
public class CatalogLocation
{

   private static Logger log = Logger.getLogger(CatalogLocation.class);

   /**
    * The catalog is assembled by taking into account all accessible resources whose name is
    * META-INF/jax-ws-catalog.xml. Each resource MUST be a valid entity catalog according to the XML Catalogs
    */
   private static final String[] catalogFilesNames =
   {"META-INF/jax-ws-catalog.xml", "WEB-INF/jax-ws-catalog.xml", "jax-ws-catalog.xml"};

   private final Resolver catologResolver;

   private final URL location;

   private boolean isLastEntityResolved = false;

   static
   {
      // If the source document contains "oasis-xml-catalog" processing instructions,
      // should they be used?
      System.setProperty("xml.catalog.allowPI", "true");
      //Which identifier is preferred, "public" or "system"?
      System.setProperty("xml.catalog.prefer", "public");
      //If non-zero, the Catalog classes will print informative and debugging messages.
      //The higher the number, the more messages.
      System.setProperty("xml.catalog.verbosity", "0");
   }

   /**
    * Create a new CatalogLocation.
    * @param url - the location of the catalog xml file
    * @throws IOException if the catalog files cannot be loaded
    */
   public CatalogLocation(URL url) throws IOException
   {
      catologResolver = new Resolver();
      catologResolver.setCatalogManager(CatalogManager.getStaticManager());
      catologResolver.setupReaders();
      catologResolver.parseCatalog(url);
      this.location=url;
   }

   /**
    * Tries to resolve the entity using the thread specific catolog resolvers
    *
    * @param publicId - Public ID of DTD, or null if it is a schema
    * @param systemId - the system ID of DTD or Schema
    * @return InputSource of entity
    * @throws MalformedURLException - if the url is wrong
    * @throws IOException - error reading the local file
    */
   public InputSource resolveEntity(String publicId, String systemId) throws MalformedURLException, IOException
   {
      String resolvedURI = catologResolver.resolveSystem(systemId);

      if (resolvedURI == null)
      {
         resolvedURI = catologResolver.resolvePublic(publicId, systemId);
      }

      if (resolvedURI != null)
      {
         final InputSource is = new InputSource();
         is.setPublicId(publicId);
         is.setSystemId(systemId);
         is.setByteStream(this.loadResource(resolvedURI));
         this.isLastEntityResolved = true;
         return is;
      }
      else
      {
         //resource could�t be resloved
         this.isLastEntityResolved = false;
         return null;
      }
   }

   /**
    * Seach the path for oasis catalog files. The classpath of
    * Thread.currentThread().getContextClassLoader()
    * is used for the lookup.
    * @return the url where the jax-ws-catalog.xml is located
    * @throws IOException if the catalog files cannot be loaded
    *
    */
   public static URL lookupCatalogFiles() throws IOException
   {
      URL url = null;
      //JAXWS-2.-0 spec, Line 27:the current context class loader MUST be used to
      //retrieve all the resources with the specified name
      ClassLoader loader = Thread.currentThread().getContextClassLoader();

      for (int i = 0; i < catalogFilesNames.length; i++)
      {
         url = loader.getResource(catalogFilesNames[i]);
         //use the first hit
         if (url != null)
         {
            break;
         }
      }

      return url;
   }

   /**
    * Returns the boolean value to inform id DTD was found in the XML file or not
    *
    *
    * @return boolean - true if DTD was found in XML
    */
   public boolean isEntityResolved()
   {
      return this.isLastEntityResolved;
   }

   /**
    *
    * Loads the resolved resource.
    *
    * @param resolvedURI - the full qualified URI of the resoved local ressource
    * @return - the inputstram represnting this resource
    * @throws IOException - if the resource cannot be opened
    */
   private InputStream loadResource(String resolvedURI) throws IOException
   {
      try
      {
         final URI toLoad = new URI(resolvedURI);
         InputStream inputStream = null;
         if (toLoad != null)
         {
            try
            {
               inputStream = new FileInputStream(new File(toLoad));
            }
            catch (IOException e)
            {
               log.error("Failed to open url stream", e);
               throw e;
            }
         }
         return inputStream;
      }
      catch (URISyntaxException e)
      {
         log.error("The URI (" + resolvedURI + ") is malfomed");
         throw new IOException("The URI (" + resolvedURI + ") is malfomed");
      }
   }

   /**
    * To catalog locations are qual if the location is equal.
    * @param other - the catlog location to compare
    * @return true if equal
    */
   public boolean equals(Object other)
   {
     boolean back=false;
      if (other!=null && other instanceof CatalogLocation){
         final CatalogLocation otherC=(CatalogLocation)other;
         back=this.location.equals(otherC.location);
      }

      return back;
   }

   /**
    * Two catalog locations have the same hash code if the location is equal.
    * @return - the hash code
    */
   public int hashCode()
   {
      return this.location.hashCode();
   }

}


/*
 * JBoss, Home of Professional Open Source
 * Copyright 2015, Red Hat, Inc., and individual contributors as indicated
 * by the @authors tag.
 *
 * 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.jboss.util.property.jmx;

import org.jboss.logging.Logger;

/**
 * A helper for setting system properties based on class availablity.

 *
 * It has a static method and an MBean wrapper for dynamic configuration.

 *
 * The class is first checked for availablity before setting the system
 * property.

 * @jmx.mbean
 *
 * @version <tt>$Revision$</tt>
 * @author  Adrian Brock
 */
public class SystemPropertyClassValue
   implements SystemPropertyClassValueMBean
{
   public static final Logger log = Logger.getLogger(SystemPropertyClassValue.class);

   /** Property name. */
   protected String property;

   /** Class Name. */
   protected String className;

   /**
    * Constructor.
    */
   public SystemPropertyClassValue()
   {
   }

   /**
    * The system property value
    *
    * @jmx.managed-attribute
    */
   public String getProperty()
   {
      return property;
   }

   /**
    * The system property value
    *
    * @jmx.managed-attribute
    */
   public void setProperty(String property)
   {
      this.property = property;
   }

   /**
    * The class name to use a value for the system property
    * when it is available
    *
    * @jmx.managed-attribute
    */
   public String getClassName()
   {
      return className;
   }

   /**
    * The class name to use a value for the system property
    * when it is available
    *
    * @jmx.managed-attribute
    */
   public void setClassName(String className)
   {
      this.className = className;
   }

   /**
    * JBoss lifecycle
    *
    * @jmx.managed-operation
    */
   public void create()
   {
      Throwable error = setSystemPropertyClassValue(property, className);
      if (error != null)
         log.trace("Error loading class " + className + " property " + property + " not set.", error);
   }

   /**
    * Sets the system property to a class when the class is available.
    *
    * @param property the property to set
    * @param className the class to set as the properties value
    * @return any error loading the class
    * @exception IllegalArgumentException for a null or empty parameter
    */
   public static Throwable setSystemPropertyClassValue(String property, String className)
   {
      // Validation
      if (property == null || property.trim().length() == 0)
         throw new IllegalArgumentException("Null or empty property");
      if (className == null || className.trim().length() == 0)
         throw new IllegalArgumentException("Null or empty class name");

      // Is the class available?
      try
      {
         Thread.currentThread().getContextClassLoader().loadClass(className);
      }
      catch (Throwable problem)
      {
         return problem;
      }

      // The class is there, set the property.
      System.setProperty(property, className);
      return null;
   }
}


/*
 * JBoss, Home of Professional Open Source
 * Copyright 2015, Red Hat, Inc., and individual contributors as indicated
 * by the @authors tag.
 *
 * 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.jboss.util;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Array;
import java.lang.NoSuchMethodException;
import java.net.URL;

import java.security.AccessController;
import java.security.CodeSource;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import java.util.*;

/**
 * A collection of Class utilities.
 *
 * @version <tt>$Revision$</tt>
 * @author  Jason Dillon
 * @author  Scott Stark
 * @author  Dimitris Andreadis
 */
@SuppressWarnings("unchecked")
public final class Classes
{
   /** The string used to separator packages */
   public static final String PACKAGE_SEPARATOR = ".";

   /** The characther used to separator packages */
   public static final char PACKAGE_SEPARATOR_CHAR = '.';

   /** The default package name. */
   public static final String DEFAULT_PACKAGE_NAME = "<default>";

   /** Format a string buffer containing the Class, Interfaces, CodeSource,
    and ClassLoader information for the given object clazz.

    @param clazz the Class
    @param results - the buffer to write the info to
    */
   public static void displayClassInfo(Class clazz, StringBuffer results)
   {
      // Print out some codebase info for the clazz
      ClassLoader cl = clazz.getClassLoader();
      results.append("\n");
      results.append(clazz.getName());
      results.append("(");
      results.append(Integer.toHexString(clazz.hashCode()));
      results.append(").ClassLoader=");
      results.append(cl);
      ClassLoader parent = cl;
      while( parent != null )
      {
         results.append("\n..");
         results.append(parent);
         URL[] urls = getClassLoaderURLs(parent);
         int length = urls != null ? urls.length : 0;
         for(int u = 0; u < length; u ++)
         {
            results.append("\n....");
            results.append(urls[u]);
         }
         if( parent != null )
            parent = parent.getParent();
      }
      CodeSource clazzCS = clazz.getProtectionDomain().getCodeSource();
      if( clazzCS != null )
      {
         results.append("\n++++CodeSource: ");
         results.append(clazzCS);
      }
      else
         results.append("\n++++Null CodeSource");

      results.append("\nImplemented Interfaces:");
      Class[] ifaces = clazz.getInterfaces();
      for(int i = 0; i < ifaces.length; i ++)
      {
         Class iface = ifaces[i];
         results.append("\n++");
         results.append(iface);
         results.append("(");
         results.append(Integer.toHexString(iface.hashCode()));
         results.append(")");
         ClassLoader loader = ifaces[i].getClassLoader();
         results.append("\n++++ClassLoader: ");
         results.append(loader);
         ProtectionDomain pd = ifaces[i].getProtectionDomain();
         CodeSource cs = pd.getCodeSource();
         if( cs != null )
         {
            results.append("\n++++CodeSource: ");
            results.append(cs);
         }
         else
            results.append("\n++++Null CodeSource");
      }
   }

   /** Use reflection to access a URL[] getURLs or URL[] getClasspath method so
    that non-URLClassLoader class loaders, or class loaders that override
    getURLs to return null or empty, can provide the true classpath info.
    * @param cl
    * @return the urls
    */
   public static URL[] getClassLoaderURLs(ClassLoader cl)
   {
      URL[] urls = {};
      try
      {
         Class returnType = urls.getClass();
         Class[] parameterTypes = {};
         Class clClass = cl.getClass();
         Method getURLs = clClass.getMethod("getURLs", parameterTypes);
         if( returnType.isAssignableFrom(getURLs.getReturnType()) )
         {
            Object[] args = {};
            urls = (URL[]) getURLs.invoke(cl, args);
         }
         if( urls == null || urls.length == 0 )
         {
            Method getCp = clClass.getMethod("getClasspath", parameterTypes);
            if( returnType.isAssignableFrom(getCp.getReturnType()) )
            {
               Object[] args = {};
               urls = (URL[]) getCp.invoke(cl, args);
            }
         }
      }
      catch(Exception ignore)
      {
      }
      return urls;
   }

   /**
    * Describe the class of an object
    *
    * @param object the object
    * @return the description
    */
   public static String getDescription(Object object)
   {
      StringBuffer buffer = new StringBuffer();
      describe(buffer, object);
      return buffer.toString();
   }

   /**
    * Describe the class of an object
    *
    * @param buffer the string buffer
    * @param object the object
    */
   public static void describe(StringBuffer buffer, Object object)
   {
      if (object == null)
         buffer.append("**null**");
      else
         describe(buffer, object.getClass());
   }

   /**
    * Describe the class
    *
    * @param buffer the string buffer
    * @param clazz the clazz
    */
   public static void describe(StringBuffer buffer, Class clazz)
   {
      if (clazz == null)
         buffer.append("**null**");
      else
      {
         buffer.append("{class=").append(clazz.getName());
         Class[] intfs = clazz.getInterfaces();
         if (intfs.length > 0)
         {
            buffer.append(" intfs=");
            for (int i = 0; i < intfs.length; ++i)
            {
               buffer.append(intfs[i].getName());
               if (i < intfs.length-1)
                  buffer.append(", ");
            }
         }
         buffer.append("}");
      }
   }

   /**
    * Get the short name of the specified class by striping off the package
    * name.
    *
    * @param classname  Class name.
    * @return           Short class name.
    */
   public static String stripPackageName(final String classname)
   {
      int idx = classname.lastIndexOf(PACKAGE_SEPARATOR);

      if (idx != -1)
         return classname.substring(idx + 1, classname.length());
      return classname;
   }

   /**
    * Get the short name of the specified class by striping off the package
    * name.
    *
    * @param type    Class name.
    * @return        Short class name.
    */
   public static String stripPackageName(final Class type)
   {
      return stripPackageName(type.getName());
   }

   /**
    * Get the package name of the specified class.
    *
    * @param classname  Class name.
    * @return           Package name or "" if the classname is in the
    *                   default package.
    *
    * @throws EmptyStringException     Classname is an empty string.
    */
   public static String getPackageName(final String classname)
   {
      if (classname.length() == 0)
         throw new EmptyStringException();

      int index = classname.lastIndexOf(PACKAGE_SEPARATOR);
      if (index != -1)
         return classname.substring(0, index);
      return "";
   }

   /**
    * Get the package name of the specified class.
    *
    * @param type    Class.
    * @return        Package name.
    */
   public static String getPackageName(final Class type)
   {
      return getPackageName(type.getName());
   }

   /**
    * Force the given class to be loaded fully.
    *
    *
This method attempts to locate a static method on the given class
    *    the attempts to invoke it with dummy arguments in the hope that
    *    the virtual machine will prepare the class for the method call and
    *    call all of the static class initializers.
    *
    * @param type    Class to force load.
    *
    * @throws NullArgumentException    Type is null.
    */
   public static void forceLoad(final Class type)
   {
      if (type == null)
         throw new NullArgumentException("type");

      // don't attempt to force primitives to load
      if (type.isPrimitive()) return;

      // don't attempt to force java.* classes to load
      String packageName = Classes.getPackageName(type);
      // System.out.println("package name: " + packageName);

      if (packageName.startsWith("java.") ||
         packageName.startsWith("javax."))
      {
         return;
      }

      // System.out.println("forcing class to load: " + type);

      try
      {
         Method methods[] = type.getDeclaredMethods();
         Method method = null;
         for (int i = 0; i < methods.length; i++)
         {
            int modifiers = methods[i].getModifiers();
            if (Modifier.isStatic(modifiers))
            {
               method = methods[i];
               break;
            }
         }

         if (method != null)
         {
            method.invoke(null, (Object[]) null);
         }
         else
         {
            type.newInstance();
         }
      }
      catch (Exception ignore)
      {
         ThrowableHandler.add(ignore);
      }
   }

   /////////////////////////////////////////////////////////////////////////
   //                               Primitives                            //
   /////////////////////////////////////////////////////////////////////////

   /** Primitive type name -> class map. */
   private static final Map PRIMITIVE_NAME_TYPE_MAP = new HashMap();

   /** Setup the primitives map. */
   static
   {
      PRIMITIVE_NAME_TYPE_MAP.put("boolean", Boolean.TYPE);
      PRIMITIVE_NAME_TYPE_MAP.put("byte", Byte.TYPE);
      PRIMITIVE_NAME_TYPE_MAP.put("char", Character.TYPE);
      PRIMITIVE_NAME_TYPE_MAP.put("short", Short.TYPE);
      PRIMITIVE_NAME_TYPE_MAP.put("int", Integer.TYPE);
      PRIMITIVE_NAME_TYPE_MAP.put("long", Long.TYPE);
      PRIMITIVE_NAME_TYPE_MAP.put("float", Float.TYPE);
      PRIMITIVE_NAME_TYPE_MAP.put("double", Double.TYPE);
   }

   /**
    * Get the primitive type for the given primitive name.
    *
    *

    * For example, "boolean" returns Boolean.TYPE and so on...
    *
    * @param name    Primitive type name (boolean, int, byte, ...)
    * @return        Primitive type or null.
    *
    * @exception IllegalArgumentException    Type is not a primitive class
    */
   public static Class getPrimitiveTypeForName(final String name)
   {
      return (Class) PRIMITIVE_NAME_TYPE_MAP.get(name);
   }

   /** Map of primitive types to their wrapper classes */
   private static final Class[] PRIMITIVE_WRAPPER_MAP = {
      Boolean.TYPE, Boolean.class,
      Byte.TYPE, Byte.class,
      Character.TYPE, Character.class,
      Double.TYPE, Double.class,
      Float.TYPE, Float.class,
      Integer.TYPE, Integer.class,
      Long.TYPE, Long.class,
      Short.TYPE, Short.class,
   };

   /**
    * Get the wrapper class for the given primitive type.
    *
    * @param type    Primitive class.
    * @return        Wrapper class for primitive.
    *
    * @exception IllegalArgumentException    Type is not a primitive class
    */
   public static Class getPrimitiveWrapper(final Class type)
   {
      if (!type.isPrimitive())
      {
         throw new IllegalArgumentException("type is not a primitive class");
      }

      for (int i = 0; i < PRIMITIVE_WRAPPER_MAP.length; i += 2)
      {
         if (type.equals(PRIMITIVE_WRAPPER_MAP[i]))
            return PRIMITIVE_WRAPPER_MAP[i + 1];
      }

      // should never get here, if we do then PRIMITIVE_WRAPPER_MAP
      // needs to be updated to include the missing mapping
      throw new UnreachableStatementException();
   }

   /**
    * Populates a list with all the interfaces implemented by the argument
    * class c and all its superclasses.
    *
    * @param allIfaces - the list to populate with the interfaces
    * @param c - the class to start scanning for interfaces
    */
   public static void getAllInterfaces(List allIfaces, Class c)
   {
      while (c != null)
      {
         Class[] ifaces = c.getInterfaces();
         for (int n = 0; n < ifaces.length; n ++)
         {
            allIfaces.add(ifaces[n]);
         }
         c = c.getSuperclass();
      }
   }

   /**
    * Returns an array containing all the unique interfaces implemented
    * by the argument class c and all its superclasses. Interfaces that
    * appear multiple times through inheritence are only accounted for once.
    *
    * @param c - the class to start scanning for interfaces
    * @return the interfaces
    */
   public static Class[] getAllUniqueInterfaces(Class c)
   {
      Set uniqueIfaces = new HashSet();
      while (c != null )
      {
         Class[] ifaces = c.getInterfaces();
         for (int n = 0; n < ifaces.length; n ++)
         {
            uniqueIfaces.add(ifaces[n]);
         }
         c = c.getSuperclass();
      }
      return (Class[])uniqueIfaces.toArray(new Class[uniqueIfaces.size()]);
   }

   /**
    * Check if the given class is a primitive wrapper class.
    *
    * @param type    Class to check.
    * @return        True if the class is a primitive wrapper.
    */
   public static boolean isPrimitiveWrapper(final Class type)
   {
      for (int i = 0; i < PRIMITIVE_WRAPPER_MAP.length; i += 2)
      {
         if (type.equals(PRIMITIVE_WRAPPER_MAP[i + 1]))
         {
            return true;
         }
      }

      return false;
   }

   /**
    * Check if the given class is a primitive class or a primitive
    * wrapper class.
    *
    * @param type    Class to check.
    * @return        True if the class is a primitive or primitive wrapper.
    */
   public static boolean isPrimitive(final Class type)
   {
      if (type.isPrimitive() || isPrimitiveWrapper(type))
      {
         return true;
      }

      return false;
   }
   /** Check type against boolean, byte, char, short, int, long, float, double.
    * @param type  The java type name
    * @return true if this is a primative type name.
    */
   public static boolean isPrimitive(final String type)
   {
      return PRIMITIVE_NAME_TYPE_MAP.containsKey(type);
   }

   /**
    * @param wrapper  a primitive wrapper type
    * @return  primitive type the passed in wrapper type corresponds to
    */
   public static Class getPrimitive(Class wrapper)
   {
      Class primitive;
      if(Integer.class == wrapper)
      {
         primitive = int.class;
      }
      else if(Long.class == wrapper)
      {
         primitive = long.class;
      }
      else if(Double.class == wrapper)
      {
         primitive = double.class;
      }
      else if(Boolean.class == wrapper)
      {
         primitive = boolean.class;
      }
      else if(Short.class == wrapper)
      {
         primitive = short.class;
      }
      else if(Float.class == wrapper)
      {
         primitive = float.class;
      }
      else if(Byte.class == wrapper)
      {
         primitive = byte.class;
      }
      else if(Character.class == wrapper)
      {
         primitive = char.class;
      }
      else
      {
         throw new IllegalArgumentException("The class is not a primitive wrapper type: " + wrapper);
      }
      return primitive;
   }

   /**
    * Instantiate a java class object
    *
    * @param expected the expected class type
    * @param property the system property defining the class
    * @param defaultClassName the default class name
    * @return the instantiated object
    */
   public static Object instantiate(Class expected, String property, String defaultClassName)
   {
      String className = getProperty(property, defaultClassName);
      Class clazz = null;
      try
      {
         clazz = loadClass(className);
      }
      catch (ClassNotFoundException e)
      {
         throw new NestedRuntimeException("Cannot load class " + className, e);
      }
      Object result = null;
      try
      {
         result = clazz.newInstance();
      }
      catch (InstantiationException e)
      {
         throw new NestedRuntimeException("Error instantiating " + className, e);
      }
      catch (IllegalAccessException e)
      {
         throw new NestedRuntimeException("Error instantiating " + className, e);
      }
      if (expected.isAssignableFrom(clazz) == false)
         throw new NestedRuntimeException("Class " + className + " from classloader " + clazz.getClassLoader() +
            " is not of the expected class " + expected + " loaded from " + expected.getClassLoader());
      return result;
   }

   /////////////////////////////////////////////////////////////////////////
   //                            Class Loading                            //
   /////////////////////////////////////////////////////////////////////////

   /**
    * This method acts equivalently to invoking
    * Thread.currentThread().getContextClassLoader().loadClass(className); but it also
    * supports primitive types and array classes of object types or primitive types.
    *
    * @param className    the qualified name of the class or the name of primitive type or
    *                     array in the same format as returned by the
    *                     java.lang.Class.getName() method.
    * @return             the Class object for the requested className
    *
    * @throws ClassNotFoundException when the classLoader can not find the requested class
    */
   public static Class loadClass(String className) throws ClassNotFoundException
   {
      return loadClass(className, Thread.currentThread().getContextClassLoader());
   }

   /**
    * This method acts equivalently to invoking classLoader.loadClass(className)
    * but it also supports primitive types and array classes of object types or
    * primitive types.
    *
    * @param className the qualified name of the class or the name of primitive
    * type or array in the same format as returned by the
    * java.lang.Class.getName() method.
    * @param classLoader  the ClassLoader used to load classes
    * @return             the Class object for the requested className
    *
    * @throws ClassNotFoundException when the classLoader can not
    * find the requested class
    */
   public static Class loadClass(String className, ClassLoader classLoader)
      throws ClassNotFoundException
   {
      // ClassLoader.loadClass() does not handle primitive types:
      //
      //   B            byte
      //   C            char
      //   D            double
      //   F            float
      //   I            int
      //   J            long
      //   S            short
      //   Z            boolean
      //   V	         void
      //
      if (className.length() == 1)
      {
         char type = className.charAt(0);
         if (type == 'B') return Byte.TYPE;
         if (type == 'C') return Character.TYPE;
         if (type == 'D') return Double.TYPE;
         if (type == 'F') return Float.TYPE;
         if (type == 'I') return Integer.TYPE;
         if (type == 'J') return Long.TYPE;
         if (type == 'S') return Short.TYPE;
         if (type == 'Z') return Boolean.TYPE;
         if (type == 'V') return Void.TYPE;
         // else throw...
         throw new ClassNotFoundException(className);
      }

      // Check for a primative type
      if( isPrimitive(className) == true )
         return (Class) Classes.PRIMITIVE_NAME_TYPE_MAP.get(className);

      // Check for the internal vm format: Lclassname;
      if (className.charAt(0) == 'L' && className.charAt(className.length() - 1) == ';')
         return classLoader.loadClass(className.substring(1, className.length() - 1));

      // first try - be optimistic
      // this will succeed for all non-array classes and array classes that have already been resolved
      //
      try
      {
         return classLoader.loadClass(className);
      }
      catch (ClassNotFoundException e)
      {
         // if it was non-array class then throw it
         if (className.charAt(0) != '[')
            throw e;
      }

      // we are now resolving array class for the first time

      // count opening braces
      int arrayDimension = 0;
      while (className.charAt(arrayDimension) == '[')
         arrayDimension++;

      // resolve component type - use recursion so that we can resolve primitive types also
      Class componentType = loadClass(className.substring(arrayDimension), classLoader);

      // construct array class
      return Array.newInstance(componentType, new int[arrayDimension]).getClass();
   }

   /**
    * Convert a list of Strings from an Interator into an array of
    * Classes (the Strings are taken as classnames).
    *
    * @param it A java.util.Iterator pointing to a Collection of Strings
    * @param cl The ClassLoader to use
    *
    * @return Array of Classes
    *
    * @throws ClassNotFoundException When a class could not be loaded from
    *         the specified ClassLoader
    */
   public final static Class<?>[] convertToJavaClasses(Iterator<String> it,
                                                    ClassLoader cl)
      throws ClassNotFoundException
   {
      ArrayList<Class<?>> classes = new ArrayList<Class<?>>();
      while (it.hasNext())
      {
         classes.add(convertToJavaClass(it.next(), cl));
      }
      return classes.toArray(new Class[classes.size()]);
   }

   /**
    * Returns attribute's getter method. If the method not found then NoSuchMethodException will be thrown.
    * @param cls  the class the attribute belongs too
    * @param attr  the attribute's name
    * @return  attribute's getter method
    * @throws NoSuchMethodException  if the getter was not found
    */
   public final static Method getAttributeGetter(Class cls, String attr) throws NoSuchMethodException
   {
      StringBuffer buf = new StringBuffer(attr.length() + 3);
      buf.append("get");
      if(Character.isLowerCase(attr.charAt(0)))
      {
         buf.append(Character.toUpperCase(attr.charAt(0)))
            .append(attr.substring(1));
      }
      else
      {
         buf.append(attr);
      }

      try
      {
         return cls.getMethod(buf.toString(), (Class[]) null);
      }
      catch (NoSuchMethodException e)
      {
         buf.replace(0, 3, "is");
         return cls.getMethod(buf.toString(), (Class[]) null);
      }
   }

   /**
    * Returns attribute's setter method. If the method not found then NoSuchMethodException will be thrown.
    * @param cls   the class the attribute belongs to
    * @param attr  the attribute's name
    * @param type  the attribute's type
    * @return  attribute's setter method
    * @throws NoSuchMethodException  if the setter was not found
    */
   public final static Method getAttributeSetter(Class cls, String attr, Class type) throws NoSuchMethodException
   {
      StringBuffer buf = new StringBuffer(attr.length() + 3);
      buf.append("set");
      if(Character.isLowerCase(attr.charAt(0)))
      {
         buf.append(Character.toUpperCase(attr.charAt(0)))
            .append(attr.substring(1));
      }
      else
      {
         buf.append(attr);
      }

      return cls.getMethod(buf.toString(), new Class[]{type});
   }

   /**
    * Convert a given String into the appropriate Class.
    *
    * @param name Name of class
    * @param cl ClassLoader to use
    *
    * @return The class for the given name
    *
    * @throws ClassNotFoundException When the class could not be found by
    *         the specified ClassLoader
    */
   private final static Class convertToJavaClass(String name,
                                                 ClassLoader cl)
      throws ClassNotFoundException
   {
      int arraySize = 0;
      while (name.endsWith("[]"))
      {
         name = name.substring(0, name.length() - 2);
         arraySize++;
      }

      // Check for a primitive type
      Class c = (Class) PRIMITIVE_NAME_TYPE_MAP.get(name);

      if (c == null)
      {
         // No primitive, try to load it from the given ClassLoader
         try
         {
            c = cl.loadClass(name);
         }
         catch (ClassNotFoundException cnfe)
         {
            throw new ClassNotFoundException("Parameter class not found: " +
               name);
         }
      }

      // if we have an array get the array class
      if (arraySize > 0)
      {
         int[] dims = new int[arraySize];
         for (int i = 0; i < arraySize; i++)
         {
            dims[i] = 1;
         }
         c = Array.newInstance(c, dims).getClass();
      }

      return c;
   }

   /**
    * Get a system property
    *
    * @param name the property name
    * @param defaultValue the default value
    */
   private static String getProperty(final String name, final String defaultValue)
   {
      return (String) AccessController.doPrivileged(
      new PrivilegedAction()
      {
         public Object run()
         {
            return System.getProperty(name, defaultValue);
         }

      });
   }
}


/*
 * JBoss, Home of Professional Open Source
 * Copyright 2015, Red Hat, Inc., and individual contributors as indicated
 * by the @authors tag.
 *
 * 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.jboss.util.propertyeditor;

import java.beans.PropertyEditorSupport;

/** A property editor for {@link java.lang.Byte}.
 *
 * @version $Revision$
 */
public class ByteEditor extends PropertyEditorSupport
{
   /** Map the argument text into and Byte using Byte.decode.
    */
   public void setAsText(final String text)
   {
      if (PropertyEditors.isNull(text))
      {
         setValue(null);
         return;
      }
      Object newValue = Byte.decode(text);
      setValue(newValue);
   }
}


/*
 * JBoss, Home of Professional Open Source
 * Copyright 2015, Red Hat, Inc., and individual contributors as indicated
 * by the @authors tag.
 *
 * 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.jboss.util.property;

/**
 * Reads properties from files specified via a system property.
 *
 *
Unless otherwise specified, propertie filenames will be read from
 *    the <tt>org.jboss.properties</tt> singleton or array property.
 *
 * @version <tt>$Revision$</tt>
 * @author  Jason Dillon
 */
public final class DefaultPropertyReader
   extends FilePropertyReader
{
   //
   // Might want to have a org.jboss.properties.property.name or something
   // property to determine what property name to read from.
   //
   // For now just use 'properties'
   //

   /** Default property name to read filenames from */
   public static final String DEFAULT_PROPERTY_NAME = "properties";

   /**
    * Construct a <tt>DefaultPropertyReader</tt> with a specified property
    * name.
    *
    * @param propertyName    Property name.
    */
   public DefaultPropertyReader(final String propertyName) {
      super(getFilenames(propertyName));
   }

   /**
    * Construct a <tt>DefaultPropertyReader</tt>.
    */
   public DefaultPropertyReader() {
      this(DEFAULT_PROPERTY_NAME);
   }

   /**
    * Get an array of filenames to load.
    *
    * @param propertyName  Property to read filenames from.
    * @return              Array of filenames.
    * @throws PropertyException
    */
   public static String[] getFilenames(final String propertyName)
      throws PropertyException
   {
      String filenames[];

      // check for singleton property first
      Object filename = PropertyManager.getProperty(propertyName);
      if (filename != null) {
         filenames = new String[] { String.valueOf(filename) };
      }
      else {
         // if no singleton property exists then look for array props
         filenames = PropertyManager.getArrayProperty(propertyName);
      }

      return filenames;
   }
}


/*
 * JBoss, Home of Professional Open Source
 * Copyright 2015, Red Hat, Inc., and individual contributors as indicated
 * by the @authors tag.
 *
 * 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.jboss.util.file;

import java.io.File;
import java.io.FilenameFilter;

/**
 * A prefix based filename filter.
 *
 * @version <tt>$Revision$</tt>
 * @author  Jason Dillon
 */
public class FilenamePrefixFilter
   implements FilenameFilter
{
   /** The prefix which files must have to be accepted. */
   protected final String prefix;

   /** Flag to signal that we want to ignore the case. */
   protected final boolean ignoreCase;

   /**
    * Construct a <tt>FilenamePrefixFilter</tt>.
    *
    * @param prefix     The prefix which files must have to be accepted.
    * @param ignoreCase <tt>True</tt> if the filter should be case-insensitive.
    */
   public FilenamePrefixFilter(final String prefix,
                               final boolean ignoreCase)
   {
      this.ignoreCase = ignoreCase;
      this.prefix = (ignoreCase ? prefix.toLowerCase() : prefix);
   }

   /**
    * Construct a case sensitive <tt>FilenamePrefixFilter</tt>.
    *
    * @param prefix  The prefix which files must have to be accepted.
    */
   public FilenamePrefixFilter(final String prefix) {
      this(prefix, false);
   }

   /**
    * Check if a file is acceptible.
    *
    * @param dir  The directory the file resides in.
    * @param name The name of the file.
    * @return     <tt>true</tt> if the file is acceptable.
    */
   public boolean accept(final File dir, final String name) {
      if (ignoreCase) {
         return name.toLowerCase().startsWith(prefix);
      }
      else {
         return name.startsWith(prefix);
      }
   }
}


/*
 * JBoss, Home of Professional Open Source
 * Copyright 2015, Red Hat, Inc., and individual contributors as indicated
 * by the @authors tag.
 *
 * 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.jboss.util.collection;

import java.lang.ref.ReferenceQueue;
import java.util.AbstractSet;
import java.util.HashSet;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Set;

import org.jboss.util.NullArgumentException;
import org.jboss.util.WeakObject;

/**
 * A <tt>Set</tt> implementation with weak elements.  An entry in
 * a <tt>WeakSet</tt> will automatically be removed when the element is no
 * longer in ordinary use.  More precisely, the presence of an given element
 * will not prevent the element from being discarded by the garbage collector,
 * that is, made finalizable, finalized, and then reclaimed.
 *
 * @version <tt>$Revision$</tt>
 * @author  Jason Dillon
 */
@SuppressWarnings("unchecked")
public class WeakSet
   extends AbstractSet
   implements Set
{
   /** The reference queue used to get object removal notifications. */
   protected final ReferenceQueue queue = new ReferenceQueue();

   /** The <tt>Set</tt> which will be used for element storage. */
   protected final Set set;

   /**
    * Construct a <tt>WeakSet</tt>.  Any elements in the given set will be
    * wrapped in {@link WeakObject} references.
    *
    * @param set  The <tt>Set</tt> which will be used for element storage.
    *
    * @throws NullArgumentException    Set is <tt>null</tt>.
    */
   public WeakSet(final Set set) {
      if (set == null)
         throw new NullArgumentException("set");

      // reset any elements to weak objects
      if (set.size() != 0) {
         Object elements[] = set.toArray();
         set.clear();

         for (int i=0; i<elements.length; i++) {
            add(elements[i]);
         }
      }

      this.set = set;
   }

   /**
    * Construct a <tt>WeakSet</tt> based on a <tt>HashSet</tt>.
    */
   public WeakSet() {
      this(new HashSet());
   }

   /**
    * Maintain the elements in the set.  Removes objects from the set that
    * have been reclaimed due to GC.
    */
   protected final void maintain() {
      WeakObject weak;
      while ((weak = (WeakObject)queue.poll()) != null) {
         set.remove(weak);
      }
   }

   /**
    * Return the size of the set.
    *
    * @return  The size of the set.
    */
   public int size() {
      maintain();

      return set.size();
   }

   /**
    * Return an iteration over the elements in the set.
    *
    * @return  An iteration over the elements in the set.
    */
   public Iterator iterator() {
      return new Iterator() {

            /** The set's iterator */
            Iterator iter = set.iterator();

            /** JBCOMMON-24, handle null values and multiple invocations of hasNext() */
            Object UNKNOWN = new Object();

            /** The next available object. */
            Object next = UNKNOWN;

            public boolean hasNext() {
               if (next != UNKNOWN) {
                  return true;
               }
               while (iter.hasNext()) {
                  WeakObject weak = (WeakObject)iter.next();
                  Object obj = null;
                  if (weak != null && (obj = weak.get()) == null) {
                     // object has been reclaimed by the GC
                     continue;
                  }
                  next = obj;
                  return true;
               }
               return false;
            }

            public Object next() {
               if ((next == UNKNOWN) && !hasNext()) {
                  throw new NoSuchElementException();
               }
               Object obj = next;
               next = UNKNOWN;

               return obj;
            }

            public void remove() {
               iter.remove();
            }
         };
   }

   /**
    * Add an element to the set.
    *
    * @param obj  Element to add to the set.
    * @return     True if the element was added.
    */
   public boolean add(final Object obj) {
      maintain();

      return set.add(WeakObject.create(obj, queue));
   }

   /**
    * Returns <tt>true</tt> if this set contains no elements.
    *
    * @return  <tt>true</tt> if this set contains no elements.
    */
   public boolean isEmpty() {
      maintain();

      return set.isEmpty();
   }

   /**
    * Returns <tt>true</tt> if this set contains the specified element.
    *
    * @param obj  Element whose presence in this set is to be tested.
    * @return     <tt>true</tt> if this set contains the specified element.
    */
   public boolean contains(final Object obj) {
      maintain();

      return set.contains(WeakObject.create(obj));
   }

   /**
    * Removes the given element from this set if it is present.
    *
    * @param obj  Object to be removed from this set, if present.
    * @return     <tt>true</tt> if the set contained the specified element.
    */
   public boolean remove(final Object obj) {
      maintain();

      return set.remove(WeakObject.create(obj));
   }

   /**
    * Removes all of the elements from this set.
    */
   public void clear() {
      set.clear();
   }

   /**
     * Returns a shallow copy of this <tt>WeakSet</tt> instance: the elements
     * themselves are not cloned.
     *
     * @return    A shallow copy of this set.
     */
   public Object clone() {
      maintain();

      try {
         return super.clone();
      }
      catch (CloneNotSupportedException e) {
         throw new InternalError();
      }
   }
}


/*
 * JBoss, Home of Professional Open Source
 * Copyright 2015, Red Hat, Inc., and individual contributors as indicated
 * by the @authors tag.
 *
 * 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.jboss.net.protocol;

import java.net.URL;
import java.net.MalformedURLException;
import java.util.HashMap;

@SuppressWarnings("unchecked")
public class URLListerFactory {
   private static HashMap defaultClasses = new HashMap();
   static {
      defaultClasses.put("file", "org.jboss.net.protocol.file.FileURLLister");
      defaultClasses.put("http", "org.jboss.net.protocol.http.DavURLLister");
      defaultClasses.put("https", "org.jboss.net.protocol.http.DavURLLister");
   }

   private HashMap classes;

   /**
    * Create a URLLister with default listers defined for file and http
    * protocols.
    */
   public URLListerFactory() {
      classes = (HashMap) defaultClasses.clone();
   }

   /**
    * Create a URL lister using the protocol from the URL
    * @param url the url defining the protocol
    * @return a URLLister capable of listing URLs of that protocol
    * @throws MalformedURLException if no lister could be found for the protocol
    */
   public URLLister createURLLister(URL url) throws MalformedURLException  {
      return createURLLister(url.getProtocol());
   }

   /**
    * Create a URL lister for the supplied protocol
    * @param protocol the protocol
    * @return a URLLister capable of listing URLs of that protocol
    * @throws MalformedURLException if no lister could be found for the protocol
    */
   public URLLister createURLLister(String protocol) throws MalformedURLException {
      try {
         String className = (String) classes.get(protocol);
         if (className == null) {
            throw new MalformedURLException("No lister class defined for protocol "+protocol);
         }

         Class<?> clazz = Thread.currentThread().getContextClassLoader().loadClass(className);
         return (URLLister) clazz.newInstance();
      } catch (ClassNotFoundException e) {
         throw new MalformedURLException(e.getMessage());
      } catch (InstantiationException e) {
         throw new MalformedURLException(e.getMessage());
      } catch (IllegalAccessException e) {
         throw new MalformedURLException(e.getMessage());
      }
   }

   /**
    * Register a URLLister class for a given protocol
    * @param protocol the protocol this class will handle
    * @param className the URLLister implementation to instanciate
    */
   public void registerListener(String protocol, String className) {
      classes.put(protocol, className);
   }
}


/*
 * JBoss, Home of Professional Open Source
 * Copyright 2015, Red Hat, Inc., and individual contributors as indicated
 * by the @authors tag.
 *
 * 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.jboss.util.file;

import java.io.File;
import java.io.FileFilter;

/**
 * A prefix based file filter.
 *
 * @version <tt>$Revision$</tt>
 * @author  Jason Dillon
 */
public class FilePrefixFilter
   implements FileFilter
{
   /** The prefix which files must have to be accepted. */
   protected final String prefix;

   /** Flag to signal that we want to ignore the case. */
   protected final boolean ignoreCase;

   /**
    * Construct a <tt>FilePrefixFilter</tt>.
    *
    * @param prefix     The prefix which files must have to be accepted.
    * @param ignoreCase <tt>True</tt> if the filter should be case-insensitive.
    */
   public FilePrefixFilter(final String prefix,
                           final boolean ignoreCase)
   {
      this.ignoreCase = ignoreCase;
      this.prefix = (ignoreCase ? prefix.toLowerCase() : prefix);
   }

   /**
    * Construct a case sensitive <tt>FilePrefixFilter</tt>.
    *
    * @param prefix  The prefix which files must have to be accepted.
    */
   public FilePrefixFilter(final String prefix) {
      this(prefix, false);
   }

   /**
    * Check if a file is acceptible.
    *
    * @param file    The file to check.
    * @return        <tt>true</tt> if the file is acceptable.
    */
   public boolean accept(final File file) {
      if (ignoreCase) {
         return file.getName().toLowerCase().startsWith(prefix);
      }
      else {
         return file.getName().startsWith(prefix);
      }
   }
}


/*
 * JBoss, Home of Professional Open Source
 * Copyright 2015, Red Hat, Inc., and individual contributors as indicated
 * by the @authors tag.
 *
 * 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.
 */

// Debug.java - Print debug messages

package org.jboss.util.xml.catalog.helpers;

/**
 * Static debugging/messaging class for Catalogs.
 *
 *
This class defines a set of static methods that can be called
 * to produce debugging messages. Messages have an associated "debug
 * level" and messages below the current setting are not displayed.

 *
 * @author Norman Walsh
 * Norman.Walsh@Sun.COM
 *
 * @version 1.0
 */
public class Debug {
  /** The internal debug level. */
  protected int debug = 0;

  /** Constructor */
  public Debug() {
    // nop
  }

  /** Set the debug level for future messages.
 * @param newDebug */
  public void setDebug(int newDebug) {
    debug = newDebug;
  }

  /** @return the current debug level. */
  public int getDebug() {
    return debug;
  }

  /**
   * Print debug message (if the debug level is high enough).
   *
   *
Prints "the message"

   *
   * @param level The debug level of this message. This message
   * will only be
   * displayed if the current debug level is at least equal to this
   * value.
   * @param message The text of the message.
   */
  public void message(int level, String message) {
    if (debug >= level) {
      System.out.println(message);
    }
  }

  /**
   * Print debug message (if the debug level is high enough).
   *
   *
Prints "the message: spec"

   *
   * @param level The debug level of this message. This message
   * will only be
   * displayd if the current debug level is at least equal to this
   * value.
   * @param message The text of the message.
   * @param spec An argument to the message.
   */
  public void message(int level, String message, String spec) {
    if (debug >= level) {
      System.out.println(message + ": " + spec);
    }
  }

  /**
   * Print debug message (if the debug level is high enough).
   *
   *
Prints "the message: spec1" and "spec2" indented on the next line.

   *
   * @param level The debug level of this message. This message
   * will only be
   * displayed if the current debug level is at least equal to this
   * value.
   * @param message The text of the message.
   * @param spec1 An argument to the message.
   * @param spec2 Another argument to the message.
   */
  public void message(int level, String message,
			     String spec1, String spec2) {
    if (debug >= level) {
      System.out.println(message + ": " + spec1);
      System.out.println("\t" + spec2);
    }
  }
}


/*
 * JBoss, Home of Professional Open Source
 * Copyright 2015, Red Hat, Inc., and individual contributors as indicated
 * by the @authors tag.
 *
 * 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.jboss.util.property;

import java.util.Properties;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.Set;
import java.util.Iterator;

import org.jboss.util.NullArgumentException;

/**
 * This is a helper class to access a group of properties with out having to
 * refer to their full names.
 *
 *
This class needs more work to be fully functional.  It should suffice
 *    for adding property listeners and getting/setting property values,
 *    but other activies might not work out so well.
 *
 * @version <tt>$Revision$</tt>
 * @author  Jason Dillon
 * @author  Adrian Brock
 */
@SuppressWarnings("unchecked")
public class PropertyGroup extends PropertyMap
{
   /** Serial version uid */
   private static final long serialVersionUID = -2557641199743063159L;
   /** Base property name */
   protected final String basename;

   /**
    * Construct a <tt>PropertyGroup</tt>.
    *
    * @param basename   Base property name.
    * @param container  Property container.
    *
    * @throws NullArgumentException    Basename is <tt>null</tt>.
    */
   public PropertyGroup(final String basename, final Properties container)
   {
      super(container);

      if (basename == null)
         throw new NullArgumentException("basename");

      this.basename = basename;
   }

   /**
    * Get the base property name for this group.
    *
    * @return  Base property name.
    */
   public final String getBaseName()
   {
      return basename;
   }

   /**
    * Make a fully qualified property name.
    *
    * @param suffix  Property name suffix.
    */
   private String makePropertyName(final String suffix)
   {
      return basename + PropertyMap.PROPERTY_NAME_SEPARATOR + suffix;
   }

   /**
    * Make a fully qualified property name.
    *
    * @param suffix  Property name suffix.
    */
   private String makePropertyName(final Object suffix)
   {
      return makePropertyName(String.valueOf(suffix));
   }

   /**
    * Check if this <tt>PropertyMap</tt> contains a given property name.
    *
    * @param name    Property name.
    * @return        True if property map or defaults contains key.
    */
   public boolean containsKey(final Object name)
   {
      if (name == null)
         throw new NullArgumentException("name");

      return super.containsKey(makePropertyName(name));
   }

   /**
    * Set a property.
    *
    * @param name    Property name.
    * @param value   Property value.
    * @return        Previous property value or <tt>null</tt>.
    */
   public Object put(final Object name, final Object value)
   {
      if (name == null)
         throw new NullArgumentException("name");

      return super.put(makePropertyName(name), value);
   }

   /**
    * Get a property
    *
    * @param name    Property name.
    * @return        Property value or <tt>null</tt>.
    */
   public Object get(final Object name)
   {
      if (name == null)
         throw new NullArgumentException("name");

      return super.get(makePropertyName(name));
   }

   /**
    * Remove a property.
    *
    * @param name    Property name.
    * @return        Removed property value.
    */
   public Object remove(final Object name)
   {
      if (name == null)
         throw new NullArgumentException("name");

      return super.remove(makePropertyName(name));
   }

   /**
    * Returns an entry set for all properties in this group.
    *
    *

    * This is currently ver inefficient, but should get the
    * job done for now.
    */
   @SuppressWarnings("unchecked")
   public Set entrySet()
   {
      final Set superSet = super.entrySet(true);

      return new java.util.AbstractSet()
      {
         private boolean isInGroup(Map.Entry entry)
         {
            String key = (String) entry.getKey();
            return key.startsWith(basename);
         }

         public int size()
         {
            Iterator iter = superSet.iterator();
            int count = 0;
            while (iter.hasNext())
            {
               Map.Entry entry = (Map.Entry) iter.next();
               if (isInGroup(entry))
               {
                  count++;
               }
            }

            return count;
         }

         public Iterator iterator()
         {
            return new Iterator()
            {
               private Iterator iter = superSet.iterator();

               private Object next;

               public boolean hasNext()
               {
                  if (next != null)
                     return true;

                  while (next == null)
                  {
                     if (iter.hasNext())
                     {
                        Map.Entry entry = (Map.Entry) iter.next();
                        if (isInGroup(entry))
                        {
                           next = entry;
                           return true;
                        }
                     }
                     else
                     {
                        break;
                     }
                  }

                  return false;
               }

               public Object next()
               {
                  if (next == null)
                     throw new java.util.NoSuchElementException();

                  Object obj = next;
                  next = null;

                  return obj;
               }

               public void remove()
               {
                  iter.remove();
               }
            };
         }
      };
   }

   /**
    * Add a bound property listener.
    *
    *
Generates a fully qualified property name and adds the listener
    *    under that name.
    *
    * @param listener   Bound property listener to add.
    */
   protected void addPropertyListener(final BoundPropertyListener listener)
   {
      // get the bound property name
      String name = makePropertyName(listener.getPropertyName());

      // get the bound listener list for the property
      List list = (List) boundListeners.get(name);

      // if list is null, then add a new list
      if (list == null)
      {
         list = new ArrayList();
         boundListeners.put(name, list);
      }

      // if listener is not in the list already, then add it
      if (!list.contains(listener))
      {
         list.add(listener);
         // notify listener that is is bound
         listener.propertyBound(this);
      }
   }

   /**
    * Remove a bound property listener.
    *
    *
Generates a fully qualified property name and removes the listener
    *    under that name.
    *
    * @param listener   Bound property listener to remove.
    * @return           True if listener was removed.
    */
   protected boolean removePropertyListener(final BoundPropertyListener listener)
   {
      // get the bound property name
      String name = makePropertyName(listener.getPropertyName());

      // get the bound listener list for the property
      List list = (List) boundListeners.get(name);
      boolean removed = false;
      if (list != null)
      {
         removed = list.remove(listener);

         // notify listener that is was unbound
         if (removed)
            listener.propertyUnbound(this);
      }

      return removed;
   }
}


/*
 * JBoss, Home of Professional Open Source
 * Copyright 2015, Red Hat, Inc., and individual contributors as indicated
 * by the @authors tag.
 *
 * 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.jboss.util.property;

import java.util.Properties;

/**
 * Provides helper methods for working with instance or class properties.
 *
 * @version <tt>$Revision$</tt>
 * @author  Jason Dillon
 */
public class PropertyContainer
   extends PropertyMap
{
   /** The serialVersionUID */
   private static final long serialVersionUID = -3347198703863412326L;
   /** The group name for this container. */
   protected String groupname = "<unknown>";

   /**
    * Initialize the container with a property group.
    * @param props
    */
   public PropertyContainer(final Properties props) {
      super(props);
   }

   /**
    * Initialize the container with a property group of the given name.
    *
    * @param groupname  Property group name.
    */
   public PropertyContainer(final String groupname) {
      this(Property.getGroup(groupname));
      this.groupname = groupname;
   }

   /**
    * Initialize the container with a property group of the given class name.
    *
    * @param type    The class whos name will be the property group name.
    */
   public PropertyContainer(final Class<?> type) {
      this(type.getName());
   }

   /**
    * Creates a {@link FieldBoundPropertyListener} for the field and
    * property name and adds it the underlying property group.
    *
    * @param name          The field name to bind values to.
    * @param propertyName  The property name to bind to.
    *
    * @throws IllegalArgumentException    Field of property name is null or
    *                                     empty.
    */
   protected void bindField(final String name, final String propertyName) {
      if (name == null || name.equals(""))
         throw new IllegalArgumentException("name");
      if (propertyName == null || propertyName.equals(""))
         throw new IllegalArgumentException("propertyName");

      addPropertyListener
         (new FieldBoundPropertyListener(this, name, propertyName));
   }

   /**
    * Creates a {@link FieldBoundPropertyListener} for the field and
    * property name and adds it the underlying property group.
    *
    * @param name    The field name and property to bind values to.
    *
    * @throws IllegalArgumentException    Field of property name is null or
    *                                     empty.
    */
   protected void bindField(final String name) {
      bindField(name, name);
   }

   /**
    * Creates a {@link MethodBoundPropertyListener} for the method and
    * property name and adds it the underlying property group.
    *
    * @param name          The method name to bind values to.
    * @param propertyName  The property name to bind to.
    *
    * @throws IllegalArgumentException    Method of property name is null or
    *                                     empty.
    */
   protected void bindMethod(final String name, final String propertyName) {
      if (name == null || name.equals(""))
         throw new IllegalArgumentException("name");
      if (propertyName == null || propertyName.equals(""))
         throw new IllegalArgumentException("propertyName");

      addPropertyListener //                opposite of field bound =(
         (new MethodBoundPropertyListener(this, propertyName, name));
   }

   /**
    * Creates a {@link MethodBoundPropertyListener} for the method and
    * property name and adds it the underlying property group.
    *
    * @param name    The method name and property to bind values to.
    *
    * @throws IllegalArgumentException    Method of property name is null or
    *                                     empty.
    */
   protected void bindMethod(final String name) {
      bindMethod(name, name);
   }

   private String makeName(final String name) {
      return groupname + "." + name;
   }

   protected void throwException(final String name)
      throws PropertyException
   {
      throw new PropertyException(makeName(name));
   }

   protected void throwException(final String name, final String msg)
      throws PropertyException
   {
      throw new PropertyException(makeName(name) + ": " + msg);
   }

   protected void throwException(final String name, final String msg, final Throwable nested)
      throws PropertyException
   {
      throw new PropertyException(makeName(name) + ": " + msg, nested);
   }

   protected void throwException(final String name, final Throwable nested)
      throws PropertyException
   {
      throw new PropertyException(makeName(name), nested);
   }
}


/*
 * JBoss, Home of Professional Open Source
 * Copyright 2015, Red Hat, Inc., and individual contributors as indicated
 * by the @authors tag.
 *
 * 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.
 */

// TR9401CatalogReader.java - Read OASIS Catalog files
package org.jboss.util.xml.catalog.readers;

import java.io.InputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Vector;

import org.jboss.util.xml.catalog.Catalog;
import org.jboss.util.xml.catalog.CatalogEntry;
import org.jboss.util.xml.catalog.CatalogException;

/**
 * Parses OASIS Open Catalog files.
 *
 *
This class reads OASIS Open Catalog files, returning a stream
 * of tokens.

 *
 *
This code interrogates the following non-standard system properties:

 *
 *

 *
xml.catalog.debug

 *

Sets the debug level. A value of 0 is assumed if the
 * property is not set or is not a number.

 *

 *
 * @see Catalog
 *
 * @author Norman Walsh
 * Norman.Walsh@Sun.COM
 *
 * @version 1.0
 */
@SuppressWarnings("unchecked")
public class TR9401CatalogReader extends TextCatalogReader {

  /**
   * Start parsing an OASIS TR9401 Open Catalog file. The file is
   * actually read and parsed
   * as needed by nextEntry.
   *
   *
In a TR9401 Catalog the 'DELEGATE' entry delegates public
   * identifiers. There is no delegate entry for system identifiers
   * or URIs.

   *
   * @throws MalformedURLException Improper fileUrl
   * @throws IOException Error reading catalog file
   */
  public void readCatalog(Catalog catalog, InputStream is)
    throws MalformedURLException, IOException {

    catfile = is;

    if (catfile == null) {
      return;
    }

    Vector unknownEntry = null;

    while (true) {
      String token = nextToken();

      if (token == null) {
	if (unknownEntry != null) {
	  catalog.unknownEntry(unknownEntry);
	  unknownEntry = null;
	}
	catfile.close();
	catfile = null;
	return;
      }

      String entryToken = null;
      if (caseSensitive) {
	entryToken = token;
      } else {
	entryToken = token.toUpperCase();
      }

      if (entryToken.equals("DELEGATE")) {
	entryToken = "DELEGATE_PUBLIC";
      }

      try {
	int type = CatalogEntry.getEntryType(entryToken);
	int numArgs = CatalogEntry.getEntryArgCount(type);
	Vector args = new Vector();

	if (unknownEntry != null) {
	  catalog.unknownEntry(unknownEntry);
	  unknownEntry = null;
	}

	for (int count = 0; count < numArgs; count++) {
	  args.addElement(nextToken());
	}

	catalog.addEntry(new CatalogEntry(entryToken, args));
      } catch (CatalogException cex) {
	if (cex.getExceptionType() == CatalogException.INVALID_ENTRY_TYPE) {
	  if (unknownEntry == null) {
	    unknownEntry = new Vector();
	  }
	  unknownEntry.addElement(token);
	} else if (cex.getExceptionType() == CatalogException.INVALID_ENTRY) {
	  catalog.getCatalogManager().debug.message(1, "Invalid catalog entry", token);
	  unknownEntry = null;
	}
      }
    }
  }
}


/*
 * JBoss, Home of Professional Open Source
 * Copyright 2015, Red Hat, Inc., and individual contributors as indicated
 * by the @authors tag.
 *
 * 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.jboss.util.collection;

import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.WeakHashMap;

/**
 * A weak class cache that instantiates does not a hold a
 * strong reference to either the classloader or class.

 *
 * It creates the class specific data in two stages
 * to avoid recursion.

 *
 * instantiate - creates the data

 * generate - fills in the details
 *
 * @param <T> exact value type
 * @author Adrian Brock
 * @author Ales Justin
 */
public abstract class WeakClassCache<T>
{
   /** The cache */
   protected final Map<ClassLoader, Map<String, WeakReference<T>>> cache = new WeakHashMap<ClassLoader, Map<String, WeakReference<T>>>();

   /**
    * Get the information for a class
    *
    * @param clazz the class
    * @return the info
    */
   public T get(Class<?> clazz)
   {
      if (clazz == null)
         throw new IllegalArgumentException("Null class");

      Map<String, WeakReference<T>> classLoaderCache = getClassLoaderCache(clazz.getClassLoader());

      WeakReference<T> weak = classLoaderCache.get(clazz.getName());
      if (weak != null)
      {
         T result = weak.get();
         if (result != null)
            return result;
      }

      T result = instantiate(clazz);

      weak = new WeakReference<T>(result);
      classLoaderCache.put(clazz.getName(), weak);

      generate(clazz, result);

      return result;
   }

   /**
    * Get the information for a class
    *
    * @param name the name
    * @param cl the classloader
    * @return the info
    * @throws ClassNotFoundException when the class cannot be found
    */
   public T get(String name, ClassLoader cl) throws ClassNotFoundException
   {
      if (name == null)
         throw new IllegalArgumentException("Null name");
      if (cl == null)
         throw new IllegalArgumentException("Null classloader");

      Class<?> clazz = cl.loadClass(name);
      return get(clazz);
   }

   /**
    * Instantiate for a class
    *
    * @param clazz the class
    * @return the result
    */
   protected abstract T instantiate(Class<?> clazz);

   /**
    * Fill in the result
    *
    * @param clazz the class
    * @param result the result
    */
   protected abstract void generate(Class<?> clazz, T result);

   /**
    * Get the cache for the classloader
    *
    * @param cl the classloader
    * @return the map
    */
   protected Map<String, WeakReference<T>> getClassLoaderCache(ClassLoader cl)
   {
      synchronized (cache)
      {
         Map<String, WeakReference<T>> result = cache.get(cl);
         if (result == null)
         {
            result = CollectionsFactory.createConcurrentReaderMap();
            cache.put(cl, result);
         }
         return result;
      }
   }
}