libreccm-legacy/ccm-core/src/com/arsdigita/kernel/URLService.java

251 lines
9.1 KiB
Java
Executable File

/*
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library 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 library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.kernel;
import com.arsdigita.persistence.OID;
import com.arsdigita.persistence.metadata.ObjectType;
import com.arsdigita.persistence.metadata.MetadataRoot;
import com.arsdigita.persistence.SessionManager;
import java.util.Map;
import java.util.HashMap;
import javax.servlet.http.HttpServletRequest;
/**
* Supports generically locating a domain object on the site.
* The URLService can produce the path (relative to the root URL) to a page
* that displays the domain object identified by a given OID.
* <P>
* The service works by delegating to a <em>URLFinder</em> based on the object
* type of the given OID.
* A URLFinder must be registered with the URLService for the object type
* in question or one of its supertypes. That URLFinder dynamically produces a
* URL path by a process that potentially involves a few database queries.</p>
*
* <p>
* The URLService is only intended for single-object lookups. On pages that
* display many objects (for example, a search results page), the URLs displayed
* for each object should <em>not</em> be obtained from the URLService (for
* performance reasons). Instead, a single "redirector page" should be the target
* of all those links. The user clicks on a link, which then uses the
* URLService to find the object's URL and redirect the user to the resulting
* URL. An example of this process is:</p>
* <ol>
* <li> User searches for objects based on keywords.</li>
* <li> Search page displays matching objects, with a link for each
* object. The targets of these links are all the same:
* .../display-result?id=:id&object_type=:object_type</li>
* <li> User clicks on one of those links.</li>
* <li> Display-result page uses the URLService to find the specified
* object's URL and redirect the user there.</li>
* </ol>
*
* The GenericURLFinder class provides a simple URLFinder that can be
* registered for many object types.
*
* @see GenericURLFinder
*
* @author Oumi Mehrotra
* @version $Id: URLService.java 287 2005-02-22 00:29:02Z sskracic $
**/
public class URLService {
private static Map s_finders = new HashMap();
/**
* Returns a URL path to a page that displays the object identified by
* the given <i>oid</i>. The URL path is relative to the server root.
* The URL is obtained by delgating to the registered or
* inherited URLFinder for the given <i>oid</i>'s object type.
*
* @throws URLFinderNotFoundException when there is no URLFinder
* registered for the given <i>oid</i>'s object type nor any of its
* supertypes.
*
* @throws NoValidURLException when the
* URLFinder registered for the given <i>oid</i>'s object type is unable
* to produce a valid non-null URL.
**/
public static String locate(OID oid)
throws URLFinderNotFoundException, NoValidURLException {
return locate(oid,null);
}
/**
* Returns a URL path to a page that displays the object identified by
* the given <i>oid</i>. The URL path is relative to the server root.
* The URL is obtained by delgating to the registered or
* inherited URLFinder for the given <i>oid</i>'s object type.
*
* @throws URLFinderNotFoundException when there is no URLFinder
* registered for the given <i>oid</i>'s object type nor any of its
* supertypes.
*
* @throws NoValidURLException when the
* URLFinder registered for the given <i>oid</i>'s object type is unable
* to produce a valid non-null URL.
**/
public static String locate(OID oid, String context)
throws URLFinderNotFoundException, NoValidURLException
{
URLFinder f = getFinder(oid.getObjectType());
if (f==null) {
throw new URLFinderNotFoundException("There is no URLFinder " +
"registered for " +
"data object type " +
oid.getObjectType().getQualifiedName());
}
String url = (context == null) ? f.find(oid) : f.find(oid,context);
if (url == null) {
throw new NoValidURLException("The URLFinder for " +
oid.getObjectType().getQualifiedName() +
"produced a null URL for " +
oid);
}
return url;
}
/**
* Registers a URLFinder for the specified data object type.
* The registered finder will be
* used by the locate method for OIDs whose type is equal to
* the specified type. That is,
* when <code>locate(x)</code> is executed, the specified
* <i>finder</i> will be used if the specified
* <i>dataObjectType</i> is equal to <code>x.getObjectType()</code>.
*
* <p>
* Any object type that does not have a finder registered
* with this service is not supported by this service.
*
* <p>
* If another finder was already registered for the specified
* object type, the previous finder is replaced and returned.
*
* @param objectType the data object type for which to register
* the specified finder
*
* @param finder the URLFinder that will handle data objects
* of the specified data object type when the
* locate method is called
*
* @return the previous finder that was
* registered with this service for this object type.
**/
public synchronized static URLFinder registerFinder(ObjectType objectType,
URLFinder finder) {
return (URLFinder) s_finders.put(objectType, finder);
}
/**
* Wrapper around registerFinder(ObjectType, URLFinder).
*
* @see #registerFinder(ObjectType, URLFinder)
**/
public synchronized static URLFinder registerFinder(String objectType,
URLFinder finder) {
MetadataRoot meta = SessionManager.getMetadataRoot();
return (URLFinder) s_finders.put(meta.getObjectType(objectType),
finder);
}
/**
* Returns the URLFinder registered for the given object type.
**/
public synchronized static
URLFinder getRegisteredFinder(ObjectType objectType)
{
return (URLFinder) s_finders.get(objectType);
}
/**
*
* Returns the URLFinder registered for the given object type.
*
**/
public synchronized static
URLFinder getRegisteredFinder(String objectType)
{
MetadataRoot meta = SessionManager.getMetadataRoot();
return (URLFinder) s_finders.get(meta.getObjectType(objectType));
}
/**
* Gets the registered or inherited URLFinder for the specified object type.
* This is the URLFinder that is registered
* for the specified object type or its closest supertype that has
* a registered URLFinder. Returns null if there is no supertype that
* has a registered URLFinder.
*
* @param objectType the object type whose registered or inherited
* URLFinder is to be returned
*
* @return the registered or inherited URLFinder for the given object type.
* Returns null if no finder is registered for the
* given type or any of its supertypes.
**/
public synchronized static URLFinder getFinder(ObjectType objectType) {
ObjectType type = objectType;
while (type!=null && !s_finders.containsKey(type)) {
type = type.getSupertype();
}
return (URLFinder) s_finders.get(type);
}
/**
*
* @see #getFinder(ObjectType)
**/
public synchronized static URLFinder getFinder(String objectType) {
MetadataRoot meta = SessionManager.getMetadataRoot();
return (URLFinder) s_finders.get(meta.getObjectType(objectType));
}
public static OID getNonencodedOID(HttpServletRequest sreq) {
if (sreq == null) {
return null;
}
String query = sreq.getQueryString();
if (query == null) {
return null;
}
int start = query.indexOf(OID_START);
if (start == -1) {
return null;
}
start = start+OID_START.length();
int end = query.indexOf(OID_END);
if (end == -1) {
end = query.length();
}
return OID.valueOf(query.substring(start, end));
}
public static final String OID_START = "oid=";
public static final String OID_END = "&";
}