HHH-8088 - Redesign Scanner contract

This commit is contained in:
Steve Ebersole 2013-03-23 13:55:48 -05:00
parent a646b9309e
commit e4c1db1e8f
4 changed files with 98 additions and 25 deletions

View File

@ -0,0 +1,67 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.jpa.boot.scan.spi;
import org.hibernate.jpa.boot.archive.spi.ArchiveContext;
import org.hibernate.jpa.boot.archive.spi.ArchiveEntryHandler;
/**
* Base class for commonality between handling class file entries and handling package-info file entries.
*
* @author Steve Ebersole
*/
public abstract class AbstractJavaArtifactArchiveEntryHandler implements ArchiveEntryHandler {
private final ScanOptions scanOptions;
protected AbstractJavaArtifactArchiveEntryHandler(ScanOptions scanOptions) {
this.scanOptions = scanOptions;
}
/**
* Check to see if the incoming name (class/package name) is either:<ul>
* <li>explicitly listed in a {@code <class/>} entry within the {@code <persistence-unit/>}</li>
* <li>whether the scan options indicate that we are allowed to detect this entry</li>
* </ul>
*
* @param context Information about the archive. Mainly whether it is the root of the PU
* @param name The class/package name
*
* @return {@code true} if the named class/package is either detectable or explicitly listed; {@code false}
* otherwise.
*/
protected boolean isListedOrDetectable(ArchiveContext context, String name) {
// IMPL NOTE : protect the isExplicitlyListed call unless needed, since it can take time in a PU
// with lots of listed classes. The other conditions are simple boolean flag checks.
if ( context.isRootUrl() ) {
return scanOptions.canDetectUnlistedClassesInRoot() || isExplicitlyListed( context, name );
}
else {
return scanOptions.canDetectUnlistedClassesInNonRoot() || isExplicitlyListed( context, name );
}
}
private boolean isExplicitlyListed(ArchiveContext context, String name) {
return context.getPersistenceUnitDescriptor().getManagedClassNames().contains( name );
}
}

View File

@ -36,25 +36,27 @@ import javassist.bytecode.ClassFile;
import org.hibernate.jpa.boot.archive.spi.ArchiveContext; import org.hibernate.jpa.boot.archive.spi.ArchiveContext;
import org.hibernate.jpa.boot.archive.spi.ArchiveEntry; import org.hibernate.jpa.boot.archive.spi.ArchiveEntry;
import org.hibernate.jpa.boot.archive.spi.ArchiveEntryHandler;
import org.hibernate.jpa.boot.archive.spi.ArchiveException; import org.hibernate.jpa.boot.archive.spi.ArchiveException;
import org.hibernate.jpa.boot.internal.ClassDescriptorImpl; import org.hibernate.jpa.boot.internal.ClassDescriptorImpl;
import org.hibernate.jpa.boot.scan.spi.ScanOptions;
import org.hibernate.jpa.boot.spi.ClassDescriptor; import org.hibernate.jpa.boot.spi.ClassDescriptor;
/** /**
* @author Steve Ebersole * Defines handling and filtering for class file entries within an archive
*/ *
public class ClassFileArchiveEntryHandler implements ArchiveEntryHandler { * @author Steve Ebersole
private final ScanOptions scanOptions; */
public class ClassFileArchiveEntryHandler extends AbstractJavaArtifactArchiveEntryHandler {
private final Callback callback; private final Callback callback;
/**
* Contract for the thing interested in being notified about accepted class descriptors.
*/
public static interface Callback { public static interface Callback {
public void locatedClass(ClassDescriptor classDescriptor); public void locatedClass(ClassDescriptor classDescriptor);
} }
public ClassFileArchiveEntryHandler(ScanOptions scanOptions, Callback callback) { public ClassFileArchiveEntryHandler(ScanOptions scanOptions, Callback callback) {
this.scanOptions = scanOptions; super( scanOptions );
this.callback = callback; this.callback = callback;
} }
@ -63,17 +65,8 @@ public class ClassFileArchiveEntryHandler implements ArchiveEntryHandler {
final ClassFile classFile = toClassFile( entry ); final ClassFile classFile = toClassFile( entry );
final ClassDescriptor classDescriptor = toClassDescriptor( classFile, entry ); final ClassDescriptor classDescriptor = toClassDescriptor( classFile, entry );
if ( ! context.getPersistenceUnitDescriptor().getManagedClassNames().contains( classDescriptor.getName() ) ) { if ( ! isListedOrDetectable( context, classDescriptor.getName() ) ) {
if ( context.isRootUrl() ) { return;
if ( ! scanOptions.canDetectUnlistedClassesInRoot() ) {
return;
}
}
else {
if ( ! scanOptions.canDetectUnlistedClassesInNonRoot() ) {
return;
}
}
} }
// we are only interested in classes with certain annotations, so see if the ClassDescriptor // we are only interested in classes with certain annotations, so see if the ClassDescriptor

View File

@ -30,12 +30,17 @@ import org.hibernate.jpa.boot.internal.MappingFileDescriptorImpl;
import org.hibernate.jpa.boot.spi.MappingFileDescriptor; import org.hibernate.jpa.boot.spi.MappingFileDescriptor;
/** /**
* @author Steve Ebersole * Defines handling and filtering for all non-class file (package-info is also a class file...) entries within an archive
*/ *
* @author Steve Ebersole
*/
public class NonClassFileArchiveEntryHandler implements ArchiveEntryHandler { public class NonClassFileArchiveEntryHandler implements ArchiveEntryHandler {
private final ScanOptions scanOptions; private final ScanOptions scanOptions;
private final Callback callback; private final Callback callback;
/**
* Contract for the thing interested in being notified about accepted mapping file descriptors.
*/
public static interface Callback { public static interface Callback {
public void locatedMappingFile(MappingFileDescriptor mappingFileDescriptor); public void locatedMappingFile(MappingFileDescriptor mappingFileDescriptor);
} }

View File

@ -25,26 +25,28 @@ package org.hibernate.jpa.boot.scan.spi;
import org.hibernate.jpa.boot.archive.spi.ArchiveContext; import org.hibernate.jpa.boot.archive.spi.ArchiveContext;
import org.hibernate.jpa.boot.archive.spi.ArchiveEntry; import org.hibernate.jpa.boot.archive.spi.ArchiveEntry;
import org.hibernate.jpa.boot.archive.spi.ArchiveEntryHandler;
import org.hibernate.jpa.boot.internal.PackageDescriptorImpl; import org.hibernate.jpa.boot.internal.PackageDescriptorImpl;
import org.hibernate.jpa.boot.spi.PackageDescriptor; import org.hibernate.jpa.boot.spi.PackageDescriptor;
import static java.io.File.separatorChar; import static java.io.File.separatorChar;
/** /**
* Defines handling and filtering for package-info file entries within an archive
*
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class PackageInfoArchiveEntryHandler implements ArchiveEntryHandler { public class PackageInfoArchiveEntryHandler extends AbstractJavaArtifactArchiveEntryHandler {
@SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
private final ScanOptions scanOptions;
private final Callback callback; private final Callback callback;
/**
* Contract for the thing interested in being notified about accepted package-info descriptors.
*/
public static interface Callback { public static interface Callback {
public void locatedPackage(PackageDescriptor packageDescriptor); public void locatedPackage(PackageDescriptor packageDescriptor);
} }
public PackageInfoArchiveEntryHandler(ScanOptions scanOptions, Callback callback) { public PackageInfoArchiveEntryHandler(ScanOptions scanOptions, Callback callback) {
this.scanOptions = scanOptions; super( scanOptions );
this.callback = callback; this.callback = callback;
} }
@ -54,6 +56,12 @@ public class PackageInfoArchiveEntryHandler implements ArchiveEntryHandler {
// the old code skipped package-info in the root package/dir... // the old code skipped package-info in the root package/dir...
return; return;
} }
if ( ! isListedOrDetectable( context, entry.getName() ) ) {
// the package is not explicitly listed, and we are not allowed to detect it.
return;
}
notifyMatchedPackage( toPackageDescriptor( entry ) ); notifyMatchedPackage( toPackageDescriptor( entry ) );
} }