blob: ec7110970bdc2cea53e2172b44e189a02a24792c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.lenya.cms.publication;
import java.util.Arrays;
import java.util.StringTokenizer;
import org.apache.commons.lang.Validate;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.excalibur.source.SourceResolver;
import org.apache.lenya.cms.metadata.MetaDataCache;
import org.apache.lenya.cms.repository.NodeFactory;
import org.apache.lenya.cms.repository.RepositoryException;
import org.apache.lenya.cms.repository.RepositoryItem;
import org.apache.lenya.cms.repository.RepositoryItemFactory;
import org.apache.lenya.cms.repository.SessionHolder;
import org.apache.lenya.utils.URLInformation;
/**
* A DocumentIdentityMap avoids the multiple instanciation of a document object.
*
* @version $Id: DocumentIdentityMap.java 264153 2005-08-29 15:11:14Z andreas $
*/
public class DocumentFactoryImpl implements DocumentFactory, RepositoryItemFactory {
private static final Log logger = LogFactory.getLog(DocumentFactoryImpl.class);
private Session session;
private MetaDataCache metaDataCache;
private SourceResolver sourceResolver;
private NodeFactory nodeFactory;
private ResourceTypeResolver resourceTypeResolver;
/**
* @return The session.
*/
public Session getSession() {
return this.session;
}
/**
* Ctor.
* @param session The session to use.
*/
public DocumentFactoryImpl(Session session) {
this.session = session;
}
/**
* Returns a document.
* @param publication The publication.
* @param area The area.
* @param uuid The document UUID.
* @param language The language.
* @return A document.
* @throws ResourceNotFoundException if an error occurs.
*/
public Document get(Publication publication, String area, String uuid, String language)
throws ResourceNotFoundException {
return get(publication, area, uuid, language, -1);
}
public Document get(Publication publication, String area, String uuid, String language,
int revision) throws ResourceNotFoundException {
if (logger.isDebugEnabled())
logger.debug(
"DocumentIdentityMap::get() called on publication [" + publication.getId()
+ "], area [" + area + "], UUID [" + uuid + "], language [" + language
+ "]");
String key = getKey(publication, area, uuid, language, revision);
if (logger.isDebugEnabled())
logger.debug(
"DocumentIdentityMap::get() got key [" + key + "] from DocumentFactory");
try {
return (Document) getRepositorySession().getRepositoryItem(this, key);
} catch (RepositoryException e) {
throw new ResourceNotFoundException(e);
}
}
protected org.apache.lenya.cms.repository.Session getRepositorySession() {
SessionHolder holder = (SessionHolder) this.session;
return holder.getRepositorySession();
}
/**
* Returns the document identified by a certain web application URL.
* @param webappUrl The web application URL.
* @return A document.
* @throws ResourceNotFoundException if an error occurs.
*/
public Document getFromURL(String webappUrl) throws ResourceNotFoundException {
String key = getKey(webappUrl);
try {
return (Document) getRepositorySession().getRepositoryItem(this, key);
} catch (RepositoryException e) {
throw new ResourceNotFoundException(e);
}
}
/**
* Builds a clone of a document for another language.
* @param document The document to clone.
* @param language The language of the target document.
* @return A document.
* @throws DocumentBuildException if an error occurs.
*/
//florent : seems never use, imply cyclic dependencies
/*
public Document getLanguageVersion(Document document, String language)
throws DocumentBuildException {
return get(document.getPublication(), document.getArea(), document.getUUID(), language);
}*/
/**
* Builds a clone of a document for another area.
* @param document The document to clone.
* @param area The area of the target document.
* @return A document.
* @throws ResourceNotFoundException if an error occurs.
*/
//florent : seems never use, imply cyclic dependencies
/*
public Document getAreaVersion(Document document, String area) throws ResourceNotFoundException {
return get(document.getPublication(), area, document.getUUID(), document.getLanguage());
}*/
/**
* Builds a document for the default language.
* @param publication The publication.
* @param area The area.
* @param documentId The document ID.
* @return A document.
* @throws ResourceNotFoundException if an error occurs.
*/
public Document get(Publication publication, String area, String documentId)
throws ResourceNotFoundException {
return get(publication, area, documentId, publication.getDefaultLanguage());
}
/**
* Checks if a string represents a valid document ID.
* @param id The string.
* @return A boolean value.
*/
public boolean isValidDocumentId(String id) {
if (!id.startsWith("/")) {
return false;
}
String[] snippets = id.split("/");
if (snippets.length < 2) {
return false;
}
for (int i = 1; i < snippets.length; i++) {
if (!snippets[i].matches("[a-zA-Z0-9\\-]+")) {
return false;
}
}
return true;
}
/**
* Checks if a webapp URL represents a document.
* @param webappUrl A web application URL.
* @return A boolean value.
* @throws ResourceNotFoundException if an error occurs.
*/
public boolean isDocument(String webappUrl) throws ResourceNotFoundException {
Validate.notNull(webappUrl);
try {
//florent URLInformation info = new URLInformation(webappUrl);
URLInformation info = new URLInformation();
String pubId = info.getPublicationId();
String[] pubIds = getPublicationIds();
if (pubId != null && Arrays.asList(pubIds).contains(pubId)) {
Publication pub = getPublication(pubId);
DocumentBuilder builder = pub.getDocumentBuilder();
return builder.isDocument(this.session, webappUrl);
} else {
return false;
}
} catch (PublicationException e) {
throw new ResourceNotFoundException(e);
}
}
/**
* Builds a document key.
* @param publication The publication.
* @param area The area.
* @param uuid The document UUID.
* @param language The language.
* @param revision
* @return A key.
*/
public String getKey(Publication publication, String area, String uuid, String language,
int revision) {
Validate.notNull(publication);
Validate.notNull(area);
Validate.notNull(uuid);
Validate.notNull(language);
return publication.getId() + ":" + area + ":" + uuid + ":" + language + ":" + revision;
}
/**
* Builds a document key.
* @param webappUrl The web application URL.
* @return A key.
*/
public String getKey(String webappUrl) {
Validate.notNull(webappUrl);
try {
if (!isDocument(webappUrl)) {
throw new RuntimeException("No document for URL [" + webappUrl + "] found.");
}
DocumentLocator locator = getLocator(webappUrl);
Publication publication = getPublication(locator.getPublicationId());
String area = locator.getArea();
String uuid = publication.getArea(area).getSite().getNode(locator.getPath()).getUuid();
return getKey(publication, area, uuid, locator.getLanguage(), -1);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
protected DocumentLocator getLocator(String webappUrl) {
DocumentLocator locator;
try {
//florent URLInformation info = new URLInformation(webappUrl);
URLInformation info = new URLInformation();
Publication publication = getPublication(info.getPublicationId());
DocumentBuilder builder = publication.getDocumentBuilder();
locator = builder.getLocator(this.session, webappUrl);
} catch (Exception e) {
throw new RuntimeException(e);
}
return locator;
}
/**
* @see org.apache.lenya.transaction.IdentifiableFactory#build(org.apache.lenya.transaction.IdentityMap,
* java.lang.String)
*/
//florent : public RepositoryItem buildItem(org.apache.lenya.cms.repository.Session session, String key) throws RepositoryException {
public RepositoryItem buildItem(String key) throws RepositoryException {
if (logger.isDebugEnabled())
logger.debug("DocumentFactory::build() called with key [" + key + "]");
StringTokenizer tokenizer = new StringTokenizer(key, ":");
String publicationId = tokenizer.nextToken();
String area = tokenizer.nextToken();
String uuid = tokenizer.nextToken();
String language = tokenizer.nextToken();
String revisionString = tokenizer.nextToken();
int revision = Integer.valueOf(revisionString).intValue();
DocumentImpl document;
try {
Publication publication = getPublication(publicationId);
DocumentBuilder builder = publication.getDocumentBuilder();
DocumentIdentifier identifier = new DocumentIdentifierImpl(publicationId, area, uuid,
language);
document = buildDocument(identifier, revision, builder);
} catch (Exception e) {
throw new RepositoryException(e);
}
if (logger.isDebugEnabled())
logger.debug("DocumentFactory::build() done.");
return document;
}
protected DocumentImpl buildDocument(DocumentIdentifier identifier, int revision,
DocumentBuilder builder) throws DocumentBuildException {
return createDocument(identifier, revision, builder);
}
/**
* Creates a new document object. Override this method to create specific document objects,
* e.g., for different document IDs.
* @param identifier The identifier.
* @param revision The revision or -1 for the latest revision.
* @param builder The document builder.
* @return A document.
* @throws DocumentBuildException when something went wrong.
*/
protected DocumentImpl createDocument(DocumentIdentifier identifier, int revision,
DocumentBuilder builder) throws DocumentBuildException {
DocumentImpl doc = new DocumentImpl(session, identifier, revision);
doc.setMetaDataCache(getMetaDataCache());
doc.setSourceResolver(getSourceResolver());
doc.setNodeFactory(this.nodeFactory);
doc.setResourceTypeResolver(this.resourceTypeResolver);
return doc;
}
public Document get(DocumentIdentifier identifier) throws ResourceNotFoundException {
try {
Publication pub = getPublication(identifier.getPublicationId());
return get(pub, identifier.getArea(), identifier.getUUID(), identifier.getLanguage());
} catch (PublicationException e) {
throw new ResourceNotFoundException(e);
}
}
public String getItemType() {
return Document.TRANSACTIONABLE_TYPE;
}
public Publication getPublication(String id) throws PublicationException {
return getPublicationManager().getPublication(this, id);
}
public String[] getPublicationIds() {
return getPublicationManager().getPublicationIds();
}
private PublicationManager pubManager;
public void setPublicationManager(PublicationManager pubManager) {
this.pubManager = pubManager;
}
public PublicationManager getPublicationManager() {
return this.pubManager;
}
public boolean existsPublication(String id) {
return Arrays.asList(getPublicationManager().getPublicationIds()).contains(id);
}
protected MetaDataCache getMetaDataCache() {
return metaDataCache;
}
public void setMetaDataCache(MetaDataCache metaDataCache) {
this.metaDataCache = metaDataCache;
}
public SourceResolver getSourceResolver() {
return sourceResolver;
}
public void setSourceResolver(SourceResolver sourceResolver) {
this.sourceResolver = sourceResolver;
}
public void setNodeFactory(NodeFactory nodeFactory) {
Validate.notNull(nodeFactory, "node factory");
this.nodeFactory = nodeFactory;
}
public void setResourceTypeResolver(ResourceTypeResolver resourceTypeResolver) {
this.resourceTypeResolver = resourceTypeResolver;
}
}