/* * Copyright 2010 Henry Coles * * 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.pitest.classpath; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.logging.Logger; import java.util.zip.ZipException; import org.pitest.functional.F; import org.pitest.functional.FCollection; import org.pitest.functional.predicate.Predicate; import org.pitest.util.Log; import org.pitest.util.PitError; import org.pitest.util.StreamUtil; public class ClassPath { private static final Logger LOG = Log.getLogger(); private final CompoundClassPathRoot root; public ClassPath() { this(ClassPath.getClassPathElementsAsFiles()); } public ClassPath(final ClassPathRoot... roots) { this(Arrays.asList(roots)); } public ClassPath(List<ClassPathRoot> roots) { this.root = new CompoundClassPathRoot(roots); } public ClassPath(final Collection<File> files) { this(createRoots(FCollection.filter(files, exists()))); } public Collection<String> classNames() { return this.root.classNames(); } // fixme should not be determining type here private static List<ClassPathRoot> createRoots(final Collection<File> files) { File lastFile = null; try { final List<ClassPathRoot> rs = new ArrayList<ClassPathRoot>(); for (final File f : files) { lastFile = f; if (f.isDirectory()) { rs.add(new DirectoryClassPathRoot(f)); } else { handleArchive(rs, f); } } return rs; } catch (final IOException ex) { throw new PitError("Error handling file " + lastFile, ex); } } private static void handleArchive(final List<ClassPathRoot> rs, final File f) throws IOException { try { if (!f.canRead()) { throw new IOException("Can't read the file " + f); } rs.add(new ArchiveClassPathRoot(f)); } catch (final ZipException ex) { LOG.warning("Can't open the archive " + f); } } public byte[] getClassData(final String classname) throws IOException { InputStream is = this.root.getData(classname); if (is != null) { try { return StreamUtil.streamToByteArray(is); } finally { is.close(); } } return null; } public URL findResource(final String name) { try { return this.root.getResource(name); } catch (final IOException exception) { return null; } } public static Collection<String> getClassPathElementsAsPaths() { final Set<String> filesAsString = new LinkedHashSet<String>(); FCollection.mapTo(getClassPathElementsAsFiles(), fileToString(), filesAsString); return filesAsString; } public static Collection<File> getClassPathElementsAsFiles() { final Set<File> us = new LinkedHashSet<File>(); FCollection.mapTo(getClassPathElementsAsAre(), stringToCanonicalFile(), us); return us; } public Collection<String> findClasses(final Predicate<String> nameFilter) { return FCollection.filter(classNames(), nameFilter); } public String getLocalClassPath() { return this.root.cacheLocation().value(); } public ClassPath getComponent(final Predicate<ClassPathRoot> predicate) { return new ClassPath(FCollection.filter(this.root, predicate).toArray( new ClassPathRoot[0])); } private static F<File, Boolean> exists() { return new F<File, Boolean>() { @Override public Boolean apply(final File a) { return a.exists() && a.canRead(); } }; } private static F<File, String> fileToString() { return new F<File, String>() { @Override public String apply(File file) { return file.getPath(); } }; } private static F<String, File> stringToCanonicalFile() { return new F<String, File>() { @Override public File apply(String fileAsString) { try { return new File(fileAsString).getCanonicalFile(); } catch (final IOException ex) { throw new PitError("Error transforming classpath element " + fileAsString, ex); } } }; } /** FIXME move somewhere common */ private static List<String> getClassPathElementsAsAre() { final String classPath = System.getProperty("java.class.path"); final String separator = File.pathSeparator; if (classPath != null) { return Arrays.asList(classPath.split(separator)); } else { return new ArrayList<String>(); } } }