/**
* Copyright (c) 2009--2014 Red Hat, Inc.
*
* This software is licensed to you under the GNU General Public License,
* version 2 (GPLv2). There is NO WARRANTY for this software, express or
* implied, including the implied warranties of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
* along with this software; if not, see
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*
* Red Hat trademarks are not licensed under GPLv2. No permission is
* granted to use or replicate Red Hat trademarks that are incorporated
* in this software or its documentation.
*/
package com.redhat.rhn.domain.channel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.log4j.Logger;
import com.redhat.rhn.domain.BaseDomainHelper;
import com.redhat.rhn.domain.common.ChecksumType;
import com.redhat.rhn.domain.errata.Errata;
import com.redhat.rhn.domain.org.Org;
import com.redhat.rhn.domain.rhnpackage.Package;
import com.redhat.rhn.domain.server.Server;
import com.redhat.rhn.domain.user.User;
import com.redhat.rhn.manager.channel.ChannelManager;
import com.redhat.rhn.manager.system.IncompatibleArchException;
import com.redhat.rhn.manager.system.SystemManager;
/**
* Channel
* @version $Rev$
*/
public class Channel extends BaseDomainHelper implements Comparable<Channel> {
/**
* Logger for this class
*/
private static Logger log = Logger.getLogger(Channel.class);
public static final String PUBLIC = "public";
public static final String PROTECTED = "protected";
public static final String PRIVATE = "private";
private static List<String> archesToSkipRepodata = new ArrayList<String>(Arrays
.asList("channel-sparc-sun-solaris", "channel-i386-sun-solaris",
"channel-sparc"));
private String baseDir;
private ChannelArch channelArch;
private ChecksumType checksumType;
private String description;
private Date endOfLife;
private String GPGKeyUrl;
private String GPGKeyId;
private String GPGKeyFp;
private Long id;
private String label;
private Date lastModified;
private Date lastSynced;
private String name;
private String access = PRIVATE;
private Org org;
private Channel parentChannel;
private ChannelProduct product;
private ProductName productName;
private Comps comps;
private String summary;
private Set<Errata> erratas = new HashSet<Errata>();
private Set<Package> packages = new HashSet<Package>();
private Set<ContentSource> sources = new HashSet<ContentSource>();
private Set<ChannelFamily> channelFamilies = new HashSet<ChannelFamily>();
private Set<DistChannelMap> distChannelMaps = new HashSet<DistChannelMap>();
private Set<Org> trustedOrgs = new HashSet<Org>();
private String maintainerName;
private String maintainerEmail;
private String maintainerPhone;
private String supportPolicy;
/**
* @param orgIn what org you want to know if it is globally subscribable in
* @return Returns whether or not this channel is globally subscribable.
*/
public boolean isGloballySubscribable(Org orgIn) {
return ChannelFactory.isGloballySubscribable(orgIn, this);
}
/**
* Sets the globally subscribable attribute for this channel
* @param orgIn what org you want to set if it is globally subscribable in
* @param value True if you want the channel to be globally subscribable,
* false if not.
*/
public void setGloballySubscribable(boolean value, Org orgIn) {
ChannelFactory.setGloballySubscribable(orgIn, this, value);
}
/**
* Returns true if this Channel is a satellite channel.
* @return true if this Channel is a satellite channel.
*/
public boolean isSatellite() {
return getChannelFamily().getLabel().startsWith(
ChannelFamilyFactory.SATELLITE_CHANNEL_FAMILY_LABEL);
}
/**
* Returns true if this Channel is a Proxy channel.
* @return true if this Channel is a Proxy channel.
*/
public boolean isProxy() {
ChannelFamily cfam = getChannelFamily();
if (cfam != null) {
return cfam.getLabel().startsWith(
ChannelFamilyFactory.PROXY_CHANNEL_FAMILY_LABEL);
}
return false;
}
/**
* Returns true if this Channel is a Rhel channel.
* @return true if this Channel is a Rhel channel.
*/
public boolean isRhelChannel() {
return org == null;
}
/**
* Returns true if this channel is of specified release (f.e. RHEL6)
* @param ver release version
* @return true if this channel is of specified release
*/
public boolean isReleaseXChannel(Integer ver) {
if (getDistChannelMaps() != null) {
for (DistChannelMap map : getDistChannelMaps()) {
if (map.getRelease().contains(ver.toString())) {
return true;
}
}
}
return false;
}
/**
* @return Returns the baseDir.
*/
public String getBaseDir() {
return baseDir;
}
/**
* @param b The baseDir to set.
*/
public void setBaseDir(String b) {
this.baseDir = b;
}
/**
* @return Returns the channelArch.
*/
public ChannelArch getChannelArch() {
return channelArch;
}
/**
* @param c The channelArch to set.
*/
public void setChannelArch(ChannelArch c) {
this.channelArch = c;
}
/**
* @return Returns the channelChecksum.
*/
public ChecksumType getChecksumType() {
return checksumType;
}
/**
* @param checksumTypeIn The checksum to set.
*/
public void setChecksumType(ChecksumType checksumTypeIn) {
this.checksumType = checksumTypeIn;
}
/**
* @param compsIn The Comps to set.
*/
public void setComps(Comps compsIn) {
this.comps = compsIn;
}
/**
* @return Returns the Comps.
*/
public Comps getComps() {
return comps;
}
/**
* @return Returns the description.
*/
public String getDescription() {
return description;
}
/**
* @param d The description to set.
*/
public void setDescription(String d) {
this.description = d;
}
/**
* @return Returns the endOfLife.
*/
public Date getEndOfLife() {
return endOfLife;
}
/**
* @param e The endOfLife to set.
*/
public void setEndOfLife(Date e) {
this.endOfLife = e;
}
/**
* @return Returns the gPGKeyFp.
*/
public String getGPGKeyFp() {
return GPGKeyFp;
}
/**
* @param k The gPGKeyFP to set.
*/
public void setGPGKeyFp(String k) {
GPGKeyFp = k;
}
/**
* @return Returns the gPGKeyId.
*/
public String getGPGKeyId() {
return GPGKeyId;
}
/**
* @param k The gPGKeyId to set.
*/
public void setGPGKeyId(String k) {
GPGKeyId = k;
}
/**
* @return Returns the gPGKeyUrl.
*/
public String getGPGKeyUrl() {
return GPGKeyUrl;
}
/**
* @param k The gPGKeyUrl to set.
*/
public void setGPGKeyUrl(String k) {
GPGKeyUrl = k;
}
/**
* @return Returns the id.
*/
public Long getId() {
return id;
}
/**
* @param i The id to set.
*/
public void setId(Long i) {
this.id = i;
}
/**
* @return Returns the label.
*/
public String getLabel() {
return label;
}
/**
* @param l The label to set.
*/
public void setLabel(String l) {
this.label = l;
}
/**
* @return Returns the lastModified.
*/
public Date getLastModified() {
return lastModified;
}
/**
* @param l The lastModified to set.
*/
public void setLastModified(Date l) {
this.lastModified = l;
}
/**
* @return Returns the lastSynced.
*/
public Date getLastSynced() {
return lastSynced;
}
/**
* @param lastSyncedIn The lastSynced to set.
*/
public void setLastSynced(Date lastSyncedIn) {
this.lastSynced = lastSyncedIn;
}
/**
* @return Returns the name.
*/
public String getName() {
return name;
}
/**
* @param n The name to set.
*/
public void setName(String n) {
this.name = n;
}
/**
* @return Returns the org.
*/
public Org getOrg() {
return org;
}
/**
* @param o The org to set.
*/
public void setOrg(Org o) {
this.org = o;
}
/**
* @return Returns the parentChannel.
*/
public Channel getParentChannel() {
return parentChannel;
}
/**
* @param p The parentChannel to set.
*/
public void setParentChannel(Channel p) {
this.parentChannel = p;
}
/**
* @return Returns the summary.
*/
public String getSummary() {
return summary;
}
/**
* @param s The summary to set.
*/
public void setSummary(String s) {
this.summary = s;
}
/**
* @return Returns the set of erratas for this channel.
*/
public Set<Errata> getErratas() {
return erratas;
}
/**
* Sets the erratas set for this channel
* @param erratasIn The set of erratas
*/
public void setErratas(Set<Errata> erratasIn) {
this.erratas = erratasIn;
}
/**
* Adds a single errata to the channel
* @param errataIn The errata to add
*/
public void addErrata(Errata errataIn) {
erratas.add(errataIn);
}
/**
* @deprecated Do not use this method
* @return Returns the set of packages for this channel.
*/
@Deprecated
public Set<Package> getPackages() {
return packages;
}
/**
* @return Returns the size of the package set for this channel.
*/
public int getPackageCount() {
// we don;t want to use packages.size()
// this could be a lot (we don't want to load all the packages
// in Rhn-server to get a single number) ...
// So we are better off using a hibernate query for the count...
return ChannelFactory.getPackageCount(this);
}
/**
* @return Returns the size of the package set for this channel.
*/
public int getErrataCount() {
return ChannelFactory.getErrataCount(this);
}
/**
* Sets the packages set for this channel
* @param packagesIn The set of erratas
*/
public void setPackages(Set<Package> packagesIn) {
this.packages = packagesIn;
}
/**
*
* @param sourcesIn The set of yum repo sources
*/
public void setSources(Set<ContentSource> sourcesIn) {
this.sources = sourcesIn;
}
/**
*
* @return set of yum repos for this channel
*/
public Set<ContentSource> getSources() {
return sources;
}
/**
* Adds a single package to the channel
* @param packageIn The package to add
* @deprecated Do not use this method.
*/
@Deprecated
public void addPackage(Package packageIn) {
if (!getChannelArch().isCompatible(packageIn.getPackageArch())) {
throw new IncompatibleArchException(packageIn.getPackageArch(),
getChannelArch());
}
packages.add(packageIn);
}
/**
* Removes a single package from the channel
* @param user the user doing the remove
* @param packageIn The package to remove
*/
public void removePackage(Package packageIn, User user) {
List<Long> list = new ArrayList<Long>();
list.add(packageIn.getId());
ChannelManager.removePackages(this, list, user);
}
/**
* Some methods for hibernate to get and set channel families. However,
* there should be only one channel family per channel.
*/
/**
* @return Returns the set of channelFamiliess for this channel.
*/
public Set<ChannelFamily> getChannelFamilies() {
return channelFamilies;
}
/**
* Sets the channelFamilies set for this channel
* @param channelFamiliesIn The set of channelFamilies
*/
public void setChannelFamilies(Set<ChannelFamily> channelFamiliesIn) {
if (channelFamiliesIn.size() > 1) {
throw new TooManyChannelFamiliesException(this.getId(),
"A channel can only have one channel family");
}
this.channelFamilies = channelFamiliesIn;
}
/**
*
* @param trustedOrgsIn set of trusted orgs for this channel
*/
public void setTrustedOrgs(Set<Org> trustedOrgsIn) {
this.trustedOrgs = trustedOrgsIn;
}
/**
*
* @return set of trusted orgs for this channel
*/
public Set<Org> getTrustedOrgs() {
return this.trustedOrgs;
}
/**
* @return number of trusted organizations that have access to this channel
*/
public int getTrustedOrgsCount() {
if (trustedOrgs != null) {
return trustedOrgs.size();
}
return 0;
}
/**
* Adds a single channelFamily to the channel
* @param channelFamilyIn The channelFamily to add
*/
public void addChannelFamily(ChannelFamily channelFamilyIn) {
if (this.getChannelFamilies().size() > 0) {
throw new TooManyChannelFamiliesException(this.getId(),
"A channel can only have one channel family");
}
channelFamilies.add(channelFamilyIn);
}
/**
* Set the channel family for this channel.
* @param channelFamilyIn The channelFamily to add
*/
public void setChannelFamily(ChannelFamily channelFamilyIn) {
channelFamilies.clear();
this.addChannelFamily(channelFamilyIn);
}
/**
* Get the channel family for this channel.
* @return the channel's family, or null if none found
*/
public ChannelFamily getChannelFamily() {
if (this.getChannelFamilies().size() == 1) {
Object[] cfams = this.getChannelFamilies().toArray();
return (ChannelFamily) cfams[0];
}
return null;
}
/**
* Returns true if this channel is considered a base channel.
* @return true if this channel is considered a base channel.
*/
public boolean isBaseChannel() {
return (getParentChannel() == null);
}
/**
* Returns true if this channel is a cloned channel.
* @return whether the channel is cloned or not
*/
public boolean isCloned() {
return false;
}
/**
* {@inheritDoc}
*/
public boolean equals(final Object other) {
if (other instanceof SelectableChannel) {
return this.equals(((SelectableChannel)other).getChannel());
}
if (!(other instanceof Channel)) {
return false;
}
Channel castOther = (Channel) other;
return new EqualsBuilder().append(getId(), castOther.getId()).isEquals();
}
/**
* {@inheritDoc}
*/
public int hashCode() {
return new HashCodeBuilder().append(getId()).toHashCode();
}
/**
* @return Returns the product.
*/
public ChannelProduct getProduct() {
return product;
}
/**
* @param productIn The product to set.
*/
public void setProduct(ChannelProduct productIn) {
this.product = productIn;
}
/**
* @return Returns the distChannelMaps.
*/
public Set<DistChannelMap> getDistChannelMaps() {
return distChannelMaps;
}
/**
* @param distChannelMapsIn The distChannelMaps to set.
*/
public void setDistChannelMaps(Set<DistChannelMap> distChannelMapsIn) {
this.distChannelMaps = distChannelMapsIn;
}
/**
* Check if this channel is subscribable by the Org passed in. Checks:
*
* 1) If channel is a Proxy or Spacewalk channel == false 2) If channel has
* 0 (or less) available subscriptions == false.
*
* @param orgIn to check available subs
* @param server to check if subscribable
* @return boolean if subscribable or not
*/
public boolean isSubscribable(Org orgIn, Server server) {
if (log.isDebugEnabled()) {
log.debug("isSubscribable.archComp: " +
SystemManager.verifyArchCompatibility(server, this));
log.debug("isProxy: " + this.isProxy());
log.debug("isSatellite: " + this.isSatellite());
}
return (SystemManager.verifyArchCompatibility(server, this) &&
!this.isProxy() && !this
.isSatellite());
}
/**
* {@inheritDoc}
*/
public String toString() {
return new ToStringBuilder(this).append("id", id).append("label", label).toString();
}
/**
* @return the productName
*/
public ProductName getProductName() {
return productName;
}
/**
* @param productNameIn the productName to set
*/
public void setProductName(ProductName productNameIn) {
this.productName = productNameIn;
}
/**
* Returns true if the access provided is a valid value.
* @param acc the access value being checked
* @return true if the access provided is valid
*/
public boolean isValidAccess(String acc) {
if (acc.equals(Channel.PUBLIC) || acc.equals(Channel.PRIVATE) ||
acc.equals(Channel.PROTECTED)) {
return true;
}
return false;
}
/**
*@param acc public, protected, or private
*/
public void setAccess(String acc) {
access = acc;
}
/**
* @return public, protected, or private
*/
public String getAccess() {
return access;
}
/**
*
* @return wheter channel is protected
*/
public boolean isProtected() {
return this.getAccess().equals(Channel.PROTECTED);
}
/**
* Returns the child channels associated to a base channel
* @param user the User needed for accessibility issues
* @return a list of child channels or empty list if there are none.
*/
public List<Channel> getAccessibleChildrenFor(User user) {
if (isBaseChannel()) {
return ChannelFactory.getAccessibleChildChannels(this, user);
}
return new ArrayList<Channel>();
}
/**
* {@inheritDoc}
*/
public int compareTo(Channel o) {
return this.getName().compareTo(o.getName());
}
/**
* @return maintainer's name
*/
public String getMaintainerName() {
return maintainerName;
}
/**
* @return maintainer's email
*/
public String getMaintainerEmail() {
return maintainerEmail;
}
/**
* @return maintainer's phone number
*/
public String getMaintainerPhone() {
return maintainerPhone;
}
/**
* @return channel's support policy
*/
public String getSupportPolicy() {
return supportPolicy;
}
/**
* @param mname maintainer's name
*/
public void setMaintainerName(String mname) {
maintainerName = mname;
}
/**
* @param email maintainer's email
*/
public void setMaintainerEmail(String email) {
maintainerEmail = email;
}
/**
* @param phone maintainer's phone number (string)
*/
public void setMaintainerPhone(String phone) {
maintainerPhone = phone;
}
/**
* @param policy channel support policy
*/
public void setSupportPolicy(String policy) {
supportPolicy = policy;
}
/**
* Created for taskomatic -- probably shouldn't be called from the webui
* @return returns if custom channel
*/
public boolean isCustom() {
return getOrg() != null;
}
/**
* Does this channel need repodata generated
* @return Returns a boolean if repodata generation Required
*/
public boolean isChannelRepodataRequired() {
// generate repodata for all channels having channel checksum set except solaris
if (archesToSkipRepodata.contains(this.channelArch.getLabel())) {
return true;
}
return checksumType != null;
}
/**
* true if the channel contains any kickstartstartable distros
* @return true if the channel contains any distros.
*/
public boolean containsDistributions() {
return ChannelFactory.containsDistributions(this);
}
/**
* get the compatible checksum type to be used for repomd.xml
* based on channel release.
* If its a custom channel use the checksum_type_id from db set at creation time
* If its RHEL-5 we use sha1 anything newer will be sha256.
* @return checksumType
*/
public String getChecksumTypeLabel() {
if ((checksumType == null) || (checksumType.getLabel() == null)) {
// each channel shall have set checksumType
return null;
}
return checksumType.getLabel();
}
/**
* @return the original Channel the channel was cloned from
*/
public Channel getOriginal() {
throw new UnsupportedOperationException();
}
}