/*!
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* 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.
*
* Copyright (c) 2002-2013 Pentaho Corporation.. All rights reserved.
*/
package org.pentaho.reporting.libraries.base.versioning;
import org.pentaho.reporting.libraries.base.util.ObjectUtilities;
import java.lang.reflect.Method;
import java.util.ArrayList;
/**
* The project information structure contains information about the current project. This is an extended version of the
* dependency information enriched with information about the boot-process and a list of dependencies.
* <p/>
* This class needs to be subclassed by each project that wants to participate in the global boot process.
*
* @author Thomas Morgner
*/
public abstract class ProjectInformation extends DependencyInformation {
private String copyright;
private String bootClass;
private ArrayList<DependencyInformation> libraries;
private ArrayList<DependencyInformation> optionalLibraries;
private VersionHelper versionHelper;
private String internalName;
/**
* Creates a new project information object with the given name.
*
* @param name the name of the project, when internal and public names are equal.
*/
protected ProjectInformation( final String name ) {
this( name, name );
}
/**
* Creates a new project information object with the given name. The internal name is used to lookup the version
* information in the manifest file, while the public name is presented to the humans.
*
* @param internalName the internal name of the project.
* @param publicName the public name of the project.
*/
protected ProjectInformation( final String internalName, final String publicName ) {
super( publicName );
if ( internalName == null ) {
this.internalName = publicName;
} else {
this.internalName = internalName;
}
this.libraries = new ArrayList<DependencyInformation>();
optionalLibraries = new ArrayList<DependencyInformation>();
}
/**
* Returs a version helper for this project. The version helper is used to extract the versioning information from the
* manifest file of the project's JAR.
*
* @return the version helper, never null.
*/
private synchronized VersionHelper getVersionHelper() {
if ( versionHelper == null ) {
versionHelper = new VersionHelper( this );
}
return versionHelper;
}
/**
* Returns the copyright string for thie project.
*
* @return the copyright string (might be null).
*/
public String getCopyright() {
return copyright;
}
/**
* Updates the copyright string for thie project.
*
* @param copyright the copyright string.
*/
protected void setCopyright( final String copyright ) {
this.copyright = copyright;
}
/**
* Returns the internal name of the project.
*
* @return the internal name, never null.
*/
public String getInternalName() {
return internalName;
}
/**
* Returns the boot class.
*
* @return the bootclass (might be null).
*/
public String getBootClass() {
return bootClass;
}
/**
* Redefines the boot class.
*
* @param bootClass the bootclass (might be null).
*/
protected void setBootClass( final String bootClass ) {
this.bootClass = bootClass;
}
/**
* Returns a list of libraries used by the project.
*
* @return the list of libraries.
*/
public DependencyInformation[] getLibraries() {
return this.libraries.toArray
( new DependencyInformation[ this.libraries.size() ] );
}
/**
* Adds a library.
*
* @param library the library.
*/
public void addLibrary( final DependencyInformation library ) {
if ( library == null ) {
throw new NullPointerException();
}
if ( this.libraries.contains( library ) ) {
throw new NullPointerException();
}
this.libraries.add( library );
}
/**
* Returns a list of optional libraries used by the project.
*
* @return the list of libraries.
*/
public DependencyInformation[] getOptionalLibraries() {
return optionalLibraries.toArray( new DependencyInformation[ optionalLibraries.size() ] );
}
/**
* Adds an optional library. These libraries will be booted, if they define a boot class. A missing class is
* considered non-fatal and it is assumed that the programm knows how to handle that.
*
* @param libraryClass the library.
*/
protected void addOptionalLibrary( final String libraryClass ) {
if ( libraryClass == null ) {
throw new NullPointerException( "Library classname must be given." );
}
final DependencyInformation depInfo = loadLibrary( libraryClass );
if ( depInfo != null ) {
this.optionalLibraries.add( depInfo );
}
}
/**
* Tries to load the dependency information for the given class.
*
* @param classname the classname of the class that contains the <code>public static DependencyInformation
* getInstance()</code> method.
* @return the dependency information for the library or null, if the library's project-info class could not be
* loaded.
*/
private DependencyInformation loadLibrary( final String classname ) {
if ( classname == null ) {
return null;
}
try {
final ClassLoader loader = ObjectUtilities.getClassLoader( getClass() );
final Class c = Class.forName( classname, false, loader );
try {
// This cast is necessary for JDK 1.5 or later
final Method m = c.getMethod( "getInstance", (Class[]) null );
return (DependencyInformation) m.invoke( null, (Object[]) null );
} catch ( Exception e ) {
// ok, fall back ...
}
return (DependencyInformation) c.newInstance();
} catch ( Exception e ) {
// ok, this library has no 'getInstance()' method. Check the
// default constructor ...
return null;
}
}
/**
* Adds an optional library. These libraries will be booted, if they define a boot class. A missing class is
* considered non-fatal and it is assumed that the programm knows how to handle that.
*
* @param library the library.
*/
protected void addOptionalLibrary( final DependencyInformation library ) {
if ( library == null ) {
throw new NullPointerException( "Library must be given." );
}
this.optionalLibraries.add( library );
}
/**
* Returns the version number from the Manifest.
*
* @return the version, or null if no version information is known.
*/
public String getVersion() {
return getVersionHelper().getVersion();
}
/**
* Returns the product ID from the Manifest.
*
* @return the product ID, or null if none is specified in the manifest.
*/
public String getProductId() {
return getVersionHelper().getProductId();
}
/**
* Returns the release milestone number from the Manifest.
*
* @return the release milestone number, or null if none is specified in the manifest.
*/
public String getReleaseMilestone() {
return getVersionHelper().getReleaseMilestone();
}
/**
* Returns the release minor version number from the Manifest.
*
* @return the release minor version number, or null if none is specified in the manifest.
*/
public String getReleaseMinor() {
return getVersionHelper().getReleaseMinor();
}
/**
* Returns the release major version number from the Manifest.
*
* @return the release major version number, or null if none is specified in the manifest.
*/
public String getReleaseMajor() {
return getVersionHelper().getReleaseMajor();
}
/**
* Returns the release candidate token from the Manifest.
*
* @return the release candidate token, or null if none is specified in the manifest.
*/
public String getReleaseCandidateToken() {
return getVersionHelper().getReleaseCandidateToken();
}
/**
* Returns the release number from the Manifest.
*
* @return the release number, or null if none is specified in the manifest.
*/
public String getReleaseNumber() {
return getVersionHelper().getReleaseNumber();
}
/**
* Returns the release build number from the Manifest.
*
* @return the release build number, or null if none is specified in the manifest.
*/
public String getReleaseBuildNumber() {
return versionHelper.getReleaseBuildNumber();
}
}