/* 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.riotfamily.pages.model; import java.util.List; import java.util.Locale; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.ManyToOne; import javax.persistence.Table; import javax.persistence.Transient; import org.hibernate.Session; import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy; import org.hibernate.annotations.CollectionOfElements; import org.riotfamily.common.hibernate.ActiveRecordBeanSupport; import org.riotfamily.common.web.support.ServletUtils; import org.riotfamily.components.model.Content; import org.riotfamily.pages.config.DefaultPageSuffixSchema; import org.riotfamily.pages.config.PageSuffixSchema; import org.riotfamily.pages.config.SitemapSchema; import org.riotfamily.pages.config.SitemapSchemaRepository; import org.springframework.util.ObjectUtils; /** * @author Felix Gnass [fgnass at neteye dot de] * @since 6.5 */ @Entity @Table(name="riot_sites") @Cache(usage=CacheConcurrencyStrategy.NONSTRICT_READ_WRITE, region="pages") public class Site extends ActiveRecordBeanSupport { private String name; private String schemaName; private String hostName; private Locale locale; private boolean enabled = true; private long position; private Set<String> aliases; private ContentPage rootPage; private Content properties; private SitemapSchemaRepository schemaRepository; private PageSuffixSchema suffixSchema; @Transient public void setSchemaRepository(SitemapSchemaRepository schemaRepository) { this.schemaRepository = schemaRepository; } @Transient public SitemapSchema getSchema() { return schemaRepository.getSchema(schemaName); } public String getSchemaName() { if (schemaName == null) { schemaName = schemaRepository.getDefaultSchemaName(); } return schemaName; } public void setSchemaName(String schemaName) { this.schemaName = schemaName; } public void setSuffixSchema(PageSuffixSchema suffixSchema) { this.suffixSchema = suffixSchema; } @Transient private PageSuffixSchema getSuffixSchema() { if (suffixSchema == null) { suffixSchema = new DefaultPageSuffixSchema(); } return suffixSchema; } public boolean isEnabled() { return this.enabled; } public void setEnabled(boolean enabled) { this.enabled = enabled; } public String getName() { if (name == null) { if (hostName != null) { name = hostName; } else if (locale != null) { name = locale.toString(); } } return name; } public void setName(String name) { this.name = name; } public Locale getLocale() { return this.locale; } public void setLocale(Locale locale) { this.locale = locale; } public String getHostName() { return this.hostName; } public void setHostName(String hostName) { this.hostName = hostName; } /** * Returns whether the given hostName matches the configured one. * Sites without a hostName will match any host. */ public boolean hostNameMatches(String hostName) { return hostNameMatches(hostName, true); } /** * Returns whether the given hostName matches the configured one. * @param hostName The hostName to match * @param greedy Whether a <code>null</code> hostName should match any host * @return <code>true</code> if the hostName matches, <code>false</code> otherwise */ public boolean hostNameMatches(String hostName, boolean greedy) { return (this.hostName == null && greedy) || (this.hostName != null && this.hostName.equals(hostName)) || (this.aliases != null && this.aliases.contains(hostName)); } @Column(name="pos") public long getPosition() { if (position == 0) { position = System.currentTimeMillis(); } return position; } public void setPosition(long position) { this.position = position; } @CollectionOfElements @Cache(usage=CacheConcurrencyStrategy.NONSTRICT_READ_WRITE, region="pages") public Set<String> getAliases() { return this.aliases; } public void setAliases(Set<String> aliases) { this.aliases = aliases; } @ManyToOne(fetch=FetchType.LAZY, cascade=CascadeType.ALL) public ContentPage getRootPage() { return rootPage; } public void setRootPage(ContentPage rootPage) { this.rootPage = rootPage; } @ManyToOne(fetch=FetchType.LAZY, cascade=CascadeType.ALL) public Content getProperties() { if (properties == null) { properties = new Content(); } return properties; } public void setProperties(Content properties) { this.properties = properties; } public Object getProperty(String key) { return getProperties().get(key); } /** */ public String makeAbsolute(boolean secure, String defaultHost, String contextPath, String path) { StringBuffer url = new StringBuffer(); if (hostName != null || defaultHost != null) { url.append(secure ? ServletUtils.SCHEME_HTTPS : ServletUtils.SCHEME_HTTP); url.append("://"); if (hostName != null) { url.append(hostName); } else { url.append(defaultHost); } } if (contextPath.length() > 0 && !path.startsWith(contextPath)) { url.append(contextPath); } url.append(path); return url.toString(); } public String getDefaultSuffix(Page page) { if (page.getParent() == null) { return ""; } return getSuffixSchema().getDefaultSuffix(page); } public boolean isValidSuffix(Page page, String suffix) { if (page.getParent() == null) { return suffix.length() == 0; } return getSuffixSchema().isValidSuffix(page, suffix); } // ---------------------------------------------------------------------- // Object identity methods // ---------------------------------------------------------------------- @Override public String toString() { return String.format("Site[name=%s,id=%s]", getName(), getId()); } @Override public int hashCode() { return getName().hashCode(); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof Site)) { return false; } Site other = (Site) obj; return ObjectUtils.nullSafeEquals(this.hostName, other.getHostName()) && ObjectUtils.nullSafeEquals(this.locale, other.getLocale()); } // ---------------------------------------------------------------------- // ActiveRecord methods // ---------------------------------------------------------------------- public void refreshIfDetached() { Session session = getSession(); if (!session.contains(this)) { session.refresh(this); } } public static Site load(Long id) { return load(Site.class, id); } public static Site loadDefaultSite() { return query(Site.class, "from {}").setMaxResults(1).cache().load(); } public static Site loadOrCreateDefaultSite() { Site site = Site.loadDefaultSite(); if (site == null) { site = new Site(); site.setLocale(Locale.getDefault()); site.setName("default"); site.save(); } return site; } public static Site loadByLocale(Locale locale) { return query(Site.class, "from {} where locale = ?", locale).load(); } public static List<Site> findAll() { return query(Site.class, "from {} order by position").cache().find(); } public static List<Site> findBySchema(SitemapSchema schema) { return query(Site.class, "from {} where schemaName = ?", schema.getName()).find(); } public static Site loadByHostName(String hostName) { Site catchAll = null; for (Site site : findAll()) { if (site.hostNameMatches(hostName, false)) { return site; } if (site.getHostName() == null && catchAll == null) { catchAll = site; } } return catchAll; } }