CPD Results

The following document contains the results of PMD's CPD 5.0.2.

Duplications

File Line
de\smartics\util\lang\classpath\ClassPathDirectoryListing.java 47
de\smartics\util\lang\ClassPathDirectoryListing.java 48
public class ClassPathDirectoryListing
{
  // ********************************* Fields *********************************

  // --- constants ------------------------------------------------------------

  // --- members --------------------------------------------------------------

  /**
   * The context to load the directory listings.
   */
  private final ClassPathContext context;

  // ****************************** Initializer *******************************

  // ****************************** Constructors ******************************

  /**
   * Default constructor.
   *
   * @param classLoader the class loader to load the directory listings.
   * @throws NullPointerException if {@code classLoader} is <code>null</code>.
   */
  public ClassPathDirectoryListing(final ClassLoader classLoader)
    throws NullPointerException
  {
    this(new ClassPathContext(classLoader, null));
  }

  /**
   * Default constructor.
   *
   * @param context the context to load the directory listings.
   * @throws NullPointerException if {@code classLoader} is <code>null</code>.
   */
  public ClassPathDirectoryListing(final ClassPathContext context)
    throws NullPointerException
  {
    Arg.checkNotNull("context", context);
    this.context = context;
  }

  // ****************************** Inner Classes *****************************

  // ********************************* Methods ********************************

  // --- init -----------------------------------------------------------------

  // --- get&set --------------------------------------------------------------

  /**
   * Returns the context to load the directory listings.
   *
   * @return the context to load the directory listings.
   */
  public final ClassPathContext getClassPathContext()
  {
    return context;
  }

  // --- business -------------------------------------------------------------

  /**
   * Lists the contents of the resource path.
   *
   * @param resourcePath the path to the resource whose contents is to be
   *          listed. The empty string returns the contents of the class
   *          loader's root directory (which is usually the parent class
   *          loader's root).
   * @return the contents of the resource as names. The list may be empty, but
   *         is never <code>null</code>.
   * @throws NullPointerException if {@code resourcePath} is <code>null</code>.
   * @throws IllegalArgumentException if resource path cannot be resolved to
   *           determine the contents. Either the protocol is unknown or there
   *           is a problem to access the resource's content physically.
   * @impl Sub classes may override this method to add additional protocol
   *       handlers. Call this method, if the derived handler does not handle
   *       the protocol.
   */
  public List<String> list(final String resourcePath)
    throws NullPointerException, IllegalArgumentException
  {
    Arg.checkNotNull("resourcePath", resourcePath);

    final URL resourcePathUrl = context.getResource(resourcePath);
    if (resourcePathUrl == null)
    {
      throw new IllegalArgumentException("Cannot find resource '"
                                         + resourcePath + "' on class path.");
    }

    final String protocol = resourcePathUrl.getProtocol();
    if ("file".equals(protocol))
    {
      return handleFile(resourcePath, resourcePathUrl);
    }
    else if ("jar".equals(protocol))
    {
      return handleJar(resourcePath, resourcePathUrl);
    }

    throw new IllegalArgumentException(
        "Protocol '" + protocol + "' is not supported to resolve resource '"
            + resourcePath + "'.");
  }

  private List<String> handleFile(final String resourcePath,
      final URL resourcePathUrl) throws IllegalArgumentException
  {
    try
    {
      final String[] contentsArray = new File(resourcePathUrl.toURI()).list();
      return Arrays.asList(contentsArray);
    }
    catch (final URISyntaxException e)
    {
      throw new IllegalArgumentException(
          "Cannot read URL derived from resource '" + resourcePath
              + "' on the class path.", e);
    }
  }

  private List<String> handleJar(final String resourcePath,
      final URL resourcePathUrl) throws IllegalArgumentException
  {
    try
    {
      final List<String> contents = new ArrayList<String>();

      final int separatorIndex = resourcePathUrl.getPath().indexOf('!');
      final String jarPath =
          resourcePathUrl.getPath().substring(5, separatorIndex);
      final JarFile jar = new JarFile(URLDecoder.decode(jarPath, "UTF-8"));
      traverseJarEntries(resourcePath, contents, jar);

      return contents;
    }
    catch (final IOException e)
    {
      throw new IllegalArgumentException("Read from JAR '" + resourcePath
                                         + "'.", e);
    }
  }

  private void traverseJarEntries(final String resourcePath,
      final List<String> contents, final JarFile jar)
  {
    final int resourcePathLength = resourcePath.length();

    final Enumeration<JarEntry> entries = jar.entries();
    while (entries.hasMoreElements())
    {
      final String name = entries.nextElement().getName();
      if (name.startsWith(resourcePath))
      {
        final String entry = name.substring(resourcePathLength);
        final String normalized = normalize(entry);

        if (normalized != null && !contents.contains(normalized))
        {
          contents.add(normalized);
        }
      }
    }
  }

  private static String normalize(final String entry)
  {
    if (StringUtils.isBlank(entry))
    {
      return null;
    }

    String normalized = entry;
    if (normalized.charAt(0) == '/')
    {
      if (entry.length() == 1)
      {
        return null;
      }
      normalized = normalized.substring(1);
    }

    final int subDirIndex = normalized.indexOf('/');
    if (subDirIndex != -1)
    {
      normalized = normalized.substring(0, subDirIndex);
    }

    return normalized;
  }

  // --- object basics --------------------------------------------------------

}
File Line
de\smartics\util\lang\classpath\ClassPathContext.java 31
de\smartics\util\lang\ClassPathContext.java 33
public final class ClassPathContext
{
  // ********************************* Fields *********************************

  // --- constants ------------------------------------------------------------

  // --- members --------------------------------------------------------------

  /**
   * The class loader to load the directory listings.
   */
  private final ClassLoader classLoader;

  /**
   * Selects the archive root to load from.
   */
  private final String archiveRoot;

  // ****************************** Initializer *******************************

  // ****************************** Constructors ******************************

  /**
   * Default constructor.
   *
   * @param classLoader the class loader to load the directory listings.
   * @param archiveRoot the value for archiveRoot.
   * @throws NullPointerException if {@code classLoader} is <code>null</code>.
   */
  public ClassPathContext(final ClassLoader classLoader,
      final String archiveRoot) throws NullPointerException
  {
    Arg.checkNotNull("classLoader", classLoader);

    this.classLoader = classLoader;
    this.archiveRoot = archiveRoot;
  }

  // ****************************** Inner Classes *****************************

  // ********************************* Methods ********************************

  // --- init -----------------------------------------------------------------

  // --- get&set --------------------------------------------------------------

  // --- business -------------------------------------------------------------

  /**
   * Constructs the URL to the resource.
   *
   * @param resource the resource whose URL is requested.
   * @return the URL to the resource or <code>null</code> if the resource cannot
   *         be found on the class path.
   */
  public URL getResource(final String resource)
  {
    if (archiveRoot == null)
    {
      return classLoader.getResource(resource);
    }

    // TODO: maybe we should simply construct the URL?
    try
    {
      for (final Enumeration<URL> en = classLoader.getResources(resource); en
          .hasMoreElements();)
      {
        final URL current = en.nextElement();
        final String urlString = current.toExternalForm();
        if (urlString.startsWith(archiveRoot))
        {
          return current;
        }
      }
    }
    catch (final IOException e)
    {
      // return null
    }
    return null;
  }

  /**
   * Opens the stream to the resource.
   *
   * @param resource the resource whose stream is requested.
   * @return the stream to the resource or <code>null</code> if the resource
   *         cannot be found on the class path. If a stream is returned, the
   *         client is responsible to close that stream.
   */
  public InputStream getResourceAsStream(final String resource)
  {
    final URL url = getResource(resource);
    if (url != null)
    {
      try
      {
        return url.openStream();
      }
      catch (final IOException e)
      {
        // return null;
      }
    }
    return null;
  }

  /**
   * Constructs the URL to the resource.
   *
   * @param resource the resource whose URL is requested.
   * @return the constructed URL.
   * @throws IllegalArgumentException if the URL to the resource cannot be
   *           constructed.
   */
  public URL createUrl(final String resource) throws IllegalArgumentException
  {
    try
    {
      final String urlString =
          (archiveRoot != null ? archiveRoot : "") + resource;
      return new URL(urlString);
    }
    catch (final MalformedURLException e)
    {
      throw new IllegalArgumentException("Cannot construct URL with resource '"
                                         + resource + "'.", e);
    }
  }

  // --- object basics --------------------------------------------------------

  /**
   * Returns the hash code of the object.
   *
   * @return the hash code.
   */
  @Override
  public int hashCode()
  {
    return ObjectUtils.hashCode(archiveRoot);
  }

  /**
   * Returns <code>true</code> if the given object is semantically equal to the
   * given object, <code>false</code> otherwise.
   *
   * @param object the instance to compare to.
   * @return <code>true</code> if the given object is semantically equal to the
   *         given object, <code>false</code> otherwise.
   */
  @Override
  public boolean equals(final Object object)
  {
    if (this == object)
    {
      return true;
    }
    else if (object == null || getClass() != object.getClass())
    {
      return false;
    }

    final ClassPathContext other = (ClassPathContext) object;

    return ObjectUtils.equals(archiveRoot, other.archiveRoot);
  }

  @Override
  public String toString()
  {
    return archiveRoot != null ? archiveRoot : "<unspecified archive root>";
  }
}