Author: keith Date: Tue Jul 8 04:32:08 2008 New Revision: 18965 URL: http://wso2.org/svn/browse/wso2?view=rev&revision=18965
Log: Adding registry patch to address https://wso2.org/jira/browse/REGISTRY-657 Added: trunk/mashup/java/modules/patches/registry/ trunk/mashup/java/modules/patches/registry/pom.xml trunk/mashup/java/modules/patches/registry/resources/ trunk/mashup/java/modules/patches/registry/resources/registry-patches.txt trunk/mashup/java/modules/patches/registry/src/ trunk/mashup/java/modules/patches/registry/src/org/ trunk/mashup/java/modules/patches/registry/src/org/wso2/ trunk/mashup/java/modules/patches/registry/src/org/wso2/registry/ trunk/mashup/java/modules/patches/registry/src/org/wso2/registry/jdbc/ trunk/mashup/java/modules/patches/registry/src/org/wso2/registry/jdbc/BasicRegistry.java trunk/mashup/java/modules/patches/registry/src/org/wso2/registry/jdbc/Repository.java Modified: trunk/mashup/java/modules/patches/pom.xml Modified: trunk/mashup/java/modules/patches/pom.xml URL: http://wso2.org/svn/browse/wso2/trunk/mashup/java/modules/patches/pom.xml?rev=18965&r1=18964&r2=18965&view=diff ============================================================================== --- trunk/mashup/java/modules/patches/pom.xml (original) +++ trunk/mashup/java/modules/patches/pom.xml Tue Jul 8 04:32:08 2008 @@ -31,6 +31,7 @@ <modules> <module>axis2</module> + <module>registry</module> <module>wsas</module> </modules> </project> Added: trunk/mashup/java/modules/patches/registry/pom.xml URL: http://wso2.org/svn/browse/wso2/trunk/mashup/java/modules/patches/registry/pom.xml?pathrev=18965 ============================================================================== --- (empty file) +++ trunk/mashup/java/modules/patches/registry/pom.xml Tue Jul 8 04:32:08 2008 @@ -0,0 +1,45 @@ +<!-- + ~ Copyright (c) 2006, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + ~ + ~ 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. + --> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + + <parent> + <groupId>org.wso2.mashup</groupId> + <artifactId>org.wso2.mashup</artifactId> + <version>SNAPSHOT</version> + </parent> + + <modelVersion>4.0.0</modelVersion> + <artifactId>wso2mashup-registry-patches</artifactId> + <packaging>jar</packaging> + <version>SNAPSHOT</version> + <name>WSO2 Mashup Server - Registry Patches</name> + <build> + <sourceDirectory>src</sourceDirectory> + <testSourceDirectory>test</testSourceDirectory> + <resources> + <resource> + <directory>src</directory> + <includes> + <include>**/*.properties</include> + <include>**/*.xml</include> + <include>**/*.xsl</include> + </includes> + </resource> + </resources> + </build> +</project> Added: trunk/mashup/java/modules/patches/registry/resources/registry-patches.txt URL: http://wso2.org/svn/browse/wso2/trunk/mashup/java/modules/patches/registry/resources/registry-patches.txt?pathrev=18965 ============================================================================== --- (empty file) +++ trunk/mashup/java/modules/patches/registry/resources/registry-patches.txt Tue Jul 8 04:32:08 2008 @@ -0,0 +1,3 @@ +JIRA issues that this patch address + +https://wso2.org/jira/browse/REGISTRY-657 Added: trunk/mashup/java/modules/patches/registry/src/org/wso2/registry/jdbc/BasicRegistry.java URL: http://wso2.org/svn/browse/wso2/trunk/mashup/java/modules/patches/registry/src/org/wso2/registry/jdbc/BasicRegistry.java?pathrev=18965 ============================================================================== --- (empty file) +++ trunk/mashup/java/modules/patches/registry/src/org/wso2/registry/jdbc/BasicRegistry.java Tue Jul 8 04:32:08 2008 @@ -0,0 +1,730 @@ +/* + * Copyright (c) 2008, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * 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.wso2.registry.jdbc; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.registry.*; +import org.wso2.registry.Collection; +import org.wso2.registry.config.RegistryContext; +import org.wso2.registry.exceptions.RegistryException; +import org.wso2.registry.exceptions.ResourceNotFoundException; +import org.wso2.registry.i18n.Messages; +import org.wso2.registry.jdbc.dao.*; +import org.wso2.registry.jdbc.handlers.RequestContext; +import org.wso2.registry.jdbc.queries.QueryProcessorManager; +import org.wso2.registry.session.CurrentSession; +import org.wso2.registry.users.UserRealm; +import org.wso2.registry.users.UserStoreException; +import org.wso2.registry.utils.AuthorizationUtils; +import org.wso2.registry.utils.RegistryUtils; +import org.wso2.registry.utils.VersionedPath; + +import java.util.*; + +public class BasicRegistry implements Registry { + + public static final Log log = LogFactory.getLog(BasicRegistry.class); + + private RegistryContext registryContext; + + private Repository repository; + private QueryProcessorManager queryProcessorManager; + private VersionRepository versionRepository; + + private ResourceDAO resourceDAO = new ResourceDAO(); + private AssociationDAO associationDAO = new AssociationDAO(); + private LogsDAO logsDAO = new LogsDAO(); + + public BasicRegistry(RegistryContext registryContext, + Repository repository, + VersionRepository versionRepository, + QueryProcessorManager queryProcessorManager) { + this.registryContext = registryContext; + this.repository = repository; + this.versionRepository = versionRepository; + this.queryProcessorManager = queryProcessorManager; + } + + public void beginTransaction() throws RegistryException { + } + + public void commitTransaction() throws RegistryException { + } + + public void rollbackTransaction() throws RegistryException { + } + + public Resource newResource() throws RegistryException { + String msg = "Transactional registry cannot create resource instances. Please use " + + "JDBCRegistry for instantiating new resource and collection instances."; + log.error(msg); + throw new RegistryException(msg); + } + + public Collection newCollection() throws RegistryException { + String msg = "Transactional registry cannot create collection instances. Please use " + + "JDBCRegistry for instantiating new resource and collection instances."; + log.error(msg); + throw new RegistryException(msg); + } + + public RegistryContext getRegistryContext() { + return registryContext; + } + + public void setRegistryContext(RegistryContext registryContext) { + this.registryContext = registryContext; + } + + /** + * Returns the resource in the given path. + * + * @param path Path of the resource. e.g. /project1/server/deployment.xml + * @return Resource instance + * @throws org.wso2.registry.exceptions.RegistryException ResourceNotFound exception is thrown if the resource is not in the + * registry + */ + public Resource get(String path) throws RegistryException { + + path = RegistryUtils.prepareGeneralPath(path); + + // check if this path refers to a resource referred by a URL query (e.g. comment) + + RequestContext requestContext = new RequestContext(this, repository); + requestContext.setResourcePath(path); + + Resource resource = registryContext.getHandlerManager().get(requestContext); + + // resource may have been fetched from the repository, to be used by handlers. if it is + // done, it has to be stored in the request context. we can just use that resource + // without fetching it again from the repository. + if (resource == null) { + resource = requestContext.getResource(); + } + + if (resource == null) { + VersionedPath versionedPath = RegistryUtils.getVersionedPath(path); + if (versionedPath.getVersion() == -1) { + resource = repository.get(path); + } else { + resource = versionRepository.get(versionedPath); + } + } + + if (resource == null) { + throw new ResourceNotFoundException(path); + } + + // if the request is for the current version of the resource, it should not be in the + // deleted state. + if (path.indexOf("?v=") == -1 && resource.getState() == RegistryConstants.DELETED_STATE) { + throw new ResourceNotFoundException(path); + } + + return resource; + } + + public Collection get(String path, int start, int pageSize) throws RegistryException { + + Collection collection; + + VersionedPath versionedPath = RegistryUtils.getVersionedPath(path); + if (versionedPath.getVersion() == -1) { + collection = repository.get(path, start, pageSize); + } else { + collection = versionRepository.get(versionedPath, start, pageSize); + } + + return collection; + } + + public boolean resourceExists(String path) throws RegistryException { + + VersionedPath versionedPath = RegistryUtils.getVersionedPath(path); + + return versionedPath.getVersion() == -1 && repository.resourceExists(path); + } + + /** + * Adds or updates resources in the registry. If there is no resource in the given path, + * resource is added. If a resource already exist in the given path, it will be replaced with + * the new resource. Implementations may use a concurrency control method to prevent concurrency + * issues. + * + * @param suggestedPath the path which we'd like to use for the new resource. + * @param resource Resource instance for the new resource + * @return the actual path that the server chose to use for our Resource + * @throws org.wso2.registry.exceptions.RegistryException + * + */ + public synchronized String put(String suggestedPath, Resource resource) + throws RegistryException { + + suggestedPath = RegistryUtils.prepareGeneralPath(suggestedPath); + + RequestContext requestContext = new RequestContext(this, repository); + requestContext.setResourcePath(suggestedPath); + requestContext.setResource(resource); + + if (!suggestedPath.equals(RegistryConstants.ROOT_PATH)) { + registryContext.getHandlerManager().putChild(requestContext); + } + + registryContext.getHandlerManager().put(requestContext); + + String actualPath = requestContext.getActualPath(); + + if (!requestContext.isProcessingComplete()) { + actualPath = suggestedPath; + repository.put(suggestedPath, resource); + + // we are always creating versions for resources (files), if the resource has changed. + if (!(resource instanceof Collection) && + ((ResourceImpl) resource).isVersionableChange()) { + createVersion(actualPath); + } + } + + if (actualPath == null) { + return suggestedPath; + } else { + return actualPath; + } + } + + public String importResource(String suggestedPath, String sourceURL, Resource metadata) + throws RegistryException { + + suggestedPath = RegistryUtils.prepareGeneralPath(suggestedPath); + + RequestContext importChildContext = new RequestContext(this, repository); + importChildContext.setResourcePath(RegistryUtils.getParentPath(suggestedPath)); + registryContext.getHandlerManager().importChild(importChildContext); + + RequestContext requestContext = new RequestContext(this, repository); + requestContext.setResourcePath(suggestedPath); + requestContext.setSourceURL(sourceURL); + requestContext.setResource(metadata); + + registryContext.getHandlerManager().importResource(requestContext); + String savedPath = requestContext.getActualPath(); + + if (!requestContext.isProcessingComplete()) { + savedPath = suggestedPath; + + // if some handlers have updated the metadata *without completing the request* we should + // capture the updated metadata here. + if (requestContext.getResource() != null) { + metadata = requestContext.getResource(); + } + + repository.importResource(suggestedPath, sourceURL, metadata); + createVersion(suggestedPath); + } + + logsDAO.addLog(savedPath, CurrentSession.getUser(), LogEntry.UPDATE, null); + + return suggestedPath; + } + + /** + * Deletes the resource in the given path. If the path refers to a directory, all child + * resources of the directory will also be deleted. + * + * @param path Path of the resource to be deleted. + * @throws org.wso2.registry.exceptions.RegistryException + * : if the user is not authorized + */ + public synchronized void delete(String path) throws RegistryException { + + RequestContext requestContext = new RequestContext(this, repository); + requestContext.setResourcePath(path); + + registryContext.getHandlerManager().delete(requestContext); + + if (!requestContext.isProcessingComplete()) { + repository.delete(path); + } + + logsDAO.addLog(path, CurrentSession.getUser(), LogEntry.DELETE_RESOURCE, null); + } + + public String rename(String currentPath, String newName) throws RegistryException { + + String newPath = repository.rename(currentPath, newName); + logsDAO.addLog(currentPath, CurrentSession.getUser(), LogEntry.RENAME, newName); + + return newPath; + } + + public String move(String currentPath, String newPath) throws RegistryException { + + String movedPath = repository.move(currentPath, newPath); + logsDAO.addLog(currentPath, CurrentSession.getUser(), LogEntry.MOVE, newPath); + + return movedPath; + } + + public String copy(String sourcePath, String targetPath) throws RegistryException { + + String copiedPath = repository.copy(sourcePath, targetPath); + logsDAO.addLog(sourcePath, CurrentSession.getUser(), LogEntry.COPY, targetPath); + + return copiedPath; + } + + public void createVersion(String path) throws RegistryException { + + versionRepository.createSnapshot(path); + } + + public String[] getVersions(String path) throws RegistryException { + + return versionRepository.getVersions(path); + } + + public void restoreVersion(String versionPath) throws RegistryException { + + versionRepository.restoreVersion(versionPath); + } + + //////////////////////////////////////////////////////// + // Associations + //////////////////////////////////////////////////////// + public void addAssociation(String sourcePath, String targetPath, String associationType) + throws RegistryException { + associationDAO.addAssociation(sourcePath, targetPath, associationType); + } + + public void removeAssociation( + String sourcePath, String targetPath, String associationType) + throws RegistryException { + associationDAO.removeAssociation(sourcePath, targetPath, associationType); + } + + public Association[] getAllAssociations(String resourcePath) throws RegistryException { + return associationDAO.getAllAssociations(resourcePath); + } + + public Association[] getAssociations(String resourcePath, String associationType) + throws RegistryException { + return associationDAO.getAllAssociationsForType(resourcePath, associationType); + } + + + //////////////////////////////////////////////////////// + // Tagging + //////////////////////////////////////////////////////// + + /** + * Applies the given tag to the resource in the given path. If the given tag is not defined in + * the registry, it will be defined. + * + * @param resourcePath Path of the resource to be tagged. + * @param tag Tag. Any string can be used for the tag. + * @throws RegistryException ResourceNotFound exception is thrown if a resource does not exist + * in the given path. + */ + public synchronized void applyTag(String resourcePath, String tag) throws RegistryException { + + // break the comma separated words into multiple tags + String[] tags = tag.split(","); + + String resourceID; + if ((resourceID = ResourceDAO.getResourceID(resourcePath)) == null) { + String msg = "Failed to apply tag " + tag + " on resource " + resourcePath + + ". Resource " + resourcePath + " does not exist."; + log.error(msg); + throw new RegistryException(msg); + } + + String userName = CurrentSession.getUser(); + + if (!AuthorizationUtils.authorize(resourceID, ActionConstants.GET)) { + String msg = "Failed to apply tag " + tag + " on resource " + resourcePath + + ". User " + userName + " is not authorized to read the resource."; + log.error(msg); + throw new RegistryException(msg); + } + + for (int i = 0; i < tags.length; i++) { + + tags[i] = tags[i].trim(); + + if (tags[i].length() == 0 || tags[i].equals(" ")) { + continue; + } + + if (TagsDAO.taggingExists(tags[i], resourceID, userName)) { + // Already there, don't bother doing it again. + return; + } + + TagsDAO.addTagging(tags[i], resourceID, userName); + logsDAO.addLog(resourcePath, userName, LogEntry.TAG, tags[i]); + } + } + + /** + * Returns the paths of the resources, which are tagged using the given tag. + * + * @param tag Tag + * @return Resource paths + */ + public TaggedResourcePath[] getResourcePathsWithTag(String tag) throws RegistryException { + + // break the tags from spaces + String[] tags = tag.trim().split(","); + + for (int i = 0; i < tags.length; i++) { + tags[i] = tags[i].trim(); + } + + List taggedPaths = new ArrayList(); + + List pathList = TagsDAO.getPathsWithAnyTag(tags); + Iterator iPaths = pathList.iterator(); + while (iPaths.hasNext()) { + String path = (String)iPaths.next(); + + TaggedResourcePath taggedResourcePath = new TaggedResourcePath(); + taggedResourcePath.setResourcePath(path); + + for (String currentTag : tags) { + long count = TagsDAO.getTagCount(path, currentTag); + taggedResourcePath.addTagCount(currentTag, count); + } + + taggedPaths.add(taggedResourcePath); + } + + return (TaggedResourcePath[])taggedPaths + .toArray(new TaggedResourcePath[taggedPaths.size()]); + } + + /** + * Returns all tags used for tagging the given resource. + * + * @param resourcePath Path of the resource + * @return Tags + * @throws RegistryException ResourceNotFound exception is thrown if a resource does not exist + * in the given path. + */ + public Tag[] getTags(String resourcePath) throws RegistryException { + + resourcePath = RegistryUtils.prepareGeneralPath(resourcePath); + resourcePath = getCurrentPath(resourcePath); + + return TagsDAO.getTagsWithCount(resourcePath); + } + + public void removeTag(String path, String tag) throws RegistryException { + + path = RegistryUtils.prepareGeneralPath(path); + + String user = CurrentSession.getUser(); + + boolean adminUser = false; + + // check is the user belongs to the admin role + try { + UserRealm userRealm = CurrentSession.getRealm(); + String[] roles = userRealm.getUserStoreReader().getUserRoles(user); + if (RegistryUtils.containsString(RegistryConstants.ADMIN_ROLE, roles)) { + adminUser = true; + } + + } catch (UserStoreException e) { + + String msg = "Failed to get roles of the current user. " + + "User will be considered as non-admin user.\n" + e.getMessage(); + log.info(msg, e); + adminUser = false; + } + + // check if the user is the admin user + // TODO - do we really need to do this check? Won't this user always be in the admin role? + if (RegistryConstants.ADMIN_USER.equals(user)) { + adminUser = true; + } + + if (adminUser) { + TagsDAO.removeTag(path, tag); + return; + } + + String author = resourceDAO.getResourceAuthor(path); + if (user.equals(author)) { + TagsDAO.removeTag(path, tag); + } else { + TagsDAO.removeTag(path, tag, user); + } + } + + //////////////////////////////////////////////////////// + // Comments + //////////////////////////////////////////////////////// + + /** + * Adds a comment to a resource. + * + * @param resourcePath Path of the resource to add the comment. + * @param comment Comment instance for the new comment. + * @throws RegistryException ResourceNotFound exception is thrown if a resource does not exist + * in the given path. + */ + public synchronized String addComment(String resourcePath, Comment comment) + throws RegistryException { + + String userName = CurrentSession.getUser(); + + String resourceID; + if ((resourceID = ResourceDAO.getResourceID(resourcePath)) == null) { + String msg = "Failed to add comment " + comment.getText() + " to resource " + + resourcePath + ". Resource " + resourcePath + " does not exist."; + log.error(msg); + throw new RegistryException(msg); + } + + if (!AuthorizationUtils.authorize(resourceID, ActionConstants.GET)) { + String msg = "Failed to add comment " + comment.getText() + " on resource " + + resourcePath + ". User " + userName + + " is not authorized to read the resource."; + log.error(msg); + throw new RegistryException(msg); + } + + String commentPath = CommentsDAO.addComment(resourceID, userName, comment); + commentPath = resourcePath + RegistryConstants.URL_SEPARATOR + "comments:" + commentPath; + logsDAO.addLog( + resourcePath, userName, LogEntry.COMMENT, comment.getText()); + + return commentPath; + } + + + public void editComment(String commentPath, String text) throws RegistryException { + + String[] parts = commentPath.split(RegistryConstants.URL_SEPARATOR); + String commentPart = parts[1]; + + if (parts.length == 2 && commentPart.startsWith("comments:")) { + String commentId = parts[1].substring(9); + CommentsDAO.updateComment(Long.parseLong(commentId), text); + } + } + + /** + * Returns all comments for the given resource. + * + * @param resourcePath Path of the resource. + * @return Array of Comment objects. + */ + public Comment[] getComments(String resourcePath) throws RegistryException { + + resourcePath = getCurrentPath(resourcePath); + + return CommentsDAO.getComments(resourcePath); + } + + //////////////////////////////////////////////////////// + // Ratings + //////////////////////////////////////////////////////// + + /** + * Rates the given resource. + * + * @param resourcePath Path of the resource. + * @param rating rating value. + * @throws RegistryException ResourceNotFound exception is thrown if a resource does not exist + * in the given path. + */ + public synchronized void rateResource(String resourcePath, int rating) + throws RegistryException { + + String userName = CurrentSession.getUser(); + + String resourceID = ResourceDAO.getResourceID(resourcePath); + + if (resourceID != null) { + + if (!AuthorizationUtils.authorize(resourceID, ActionConstants.GET)) { + String msg = "Failed to rate resource " + resourcePath + " with rating " + rating + + ". User " + userName + " is not authorized to read the resource."; + log.error(msg); + throw new RegistryException(msg); + } + + if (RatingsDAO.ratingExists(resourceID, userName)) { + + RatingsDAO.updateRating(resourceID, userName, rating); + + log.info("Updated the rating on the resource " + + resourcePath + " by user " + userName); + } else { + RatingsDAO.addRating(resourceID, userName, rating); + } + + logsDAO.addLog(resourcePath, + userName, LogEntry.RATING, Integer.toString(rating)); + + } else { + String msg = Messages.getMessage("rate.on.null.artfact", resourcePath); + log.error(msg); + throw new RegistryException(msg); + } + } + + /** + * Returns the average rating (from all users) for the given resource. + * + * @param resourcePath Path of the resource. + * @return average rating. + */ + public float getAverageRating(String resourcePath) throws RegistryException { + + return RatingsDAO.getAverageRating(resourcePath); + } + + public int getRating(String path, String userName) throws RegistryException { + + return RatingsDAO.getRating(path, userName); + } + + ////////////////////////////////////////////////////////////////////////////// + // Extensible searching API + ////////////////////////////////////////////////////////////////////////////// + + public Collection executeQuery(String path, Map parameters) throws RegistryException { + + Resource query = get(path); + + return queryProcessorManager.executeQuery(query, parameters); + } + + + private String getCurrentPath(String resourcePath) { + String currentPath = resourcePath; + if (resourcePath.indexOf("?") > 0) { + currentPath = resourcePath.split("\\?")[0]; + } else if (resourcePath.indexOf(RegistryConstants.URL_SEPARATOR) > 0) { + currentPath = resourcePath.split("\\;")[0]; + } + + return currentPath; + } + + public LogEntry[] getLogs(String resourcePath, + int action, + String userName, + Date from, Date to, boolean recentFirst) throws RegistryException { + + List logEntryList = + logsDAO.getLogs(resourcePath, action, userName, from, to, recentFirst); + + LogEntry[] logEntries = new LogEntry[logEntryList.size()]; + for (int i = 0; i < logEntryList.size(); i++) { + logEntries[i] = (LogEntry)logEntryList.get(i); + } + + return logEntries; + } + + + public LogEntryCollection getLogCollection(String resourcePath, + int action, + String userName, + Date from, + Date to, + boolean recentFirst) throws RegistryException { + LogEntryCollection logEntryCollection = new LogEntryCollection(); + logEntryCollection.setLogCount(logsDAO.getLogsCount(resourcePath,action,userName,from,to,recentFirst)); + return logEntryCollection; + } + + public String[] getAvailableAspects() { + return registryContext.getAspectNames(); + } + + public void associateAspect(String resourcePath, String name) throws RegistryException { + //TODO need to do the security validation here + Resource resource = get(resourcePath); + Aspect aspect = getAspect(name); + if (aspect == null) { + throw new RegistryException("Couldn't find aspect '" + name + "'"); + } + aspect.associate(resource, this); + resource.addAspect(name); + put(resource.getPath(), resource); + } + + private Aspect getAspect(String name) throws RegistryException { + return registryContext.getAspect(name); + } + + //public void addAspect(String name, Aspect aspect) { + // aspects.put(name, aspect); + //} + + public Aspect getResourceAspect(Resource resource, String aspectName) + throws RegistryException { + + Aspect aspect = getAspect(aspectName); + if (aspect == null) { + throw new RegistryException("Aspect '" + aspectName + "' is not registered!"); + } + + // Confirm this aspect is associated with this Resource + List<String> resourceAspects = resource.getAspects(); + if (resourceAspects == null || !resourceAspects.contains(aspectName)) { + throw new RegistryException("Resource at '" + resource.getPath() + + "' not associated with aspect '" + aspectName + "'"); + } + + return aspect; + } + + public void invokeAspect(String resourcePath, String aspectName, String action) + throws RegistryException { + + Resource resource = get(resourcePath); + + Aspect aspect = getResourceAspect(resource, aspectName); + RequestContext context = new RequestContext(this, repository); + context.setResource(resource); + +// List aspectNames = resource.getPropertyValues(Aspect.AVAILABLE_ASPECTS); +// if (aspectNames == null) { +// throw new RegistryException("No aspect are associated with the resource"); +// } + + aspect.invoke(context, action); + put(resourcePath, resource); + } + + public String[] getAspectActions(String resourcePath, String aspectName) + throws RegistryException { + + Resource resource = get(resourcePath); + Aspect aspect = getResourceAspect(resource, aspectName); + + RequestContext context = new RequestContext(this, repository); + context.setResource(resource); + return aspect.getAvailableActions(context); + } +} Added: trunk/mashup/java/modules/patches/registry/src/org/wso2/registry/jdbc/Repository.java URL: http://wso2.org/svn/browse/wso2/trunk/mashup/java/modules/patches/registry/src/org/wso2/registry/jdbc/Repository.java?pathrev=18965 ============================================================================== --- (empty file) +++ trunk/mashup/java/modules/patches/registry/src/org/wso2/registry/jdbc/Repository.java Tue Jul 8 04:32:08 2008 @@ -0,0 +1,552 @@ +/* + * Copyright (c) 2008, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * 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.wso2.registry.jdbc; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.registry.*; +import org.wso2.registry.exceptions.RegistryException; +import org.wso2.registry.jdbc.dao.*; +import org.wso2.registry.secure.AuthorizationFailedException; +import org.wso2.registry.session.CurrentSession; +import org.wso2.registry.utils.AuthorizationUtils; +import org.wso2.registry.utils.RegistryUtils; +import org.wso2.registry.utils.UUIDGenerator; + +import javax.sql.DataSource; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.util.Iterator; +import java.util.List; + +/** + * Encapsulates the retrieving, storing, modifing and deleting of resources. This class only deals + * with the current versions of resources and it is unware of any versioning or snapshot activity. + * Only the current version related tables are accessed and updated from the methods of this class. + */ +public class Repository { + + public static final Log log = LogFactory.getLog(Repository.class); + + private ResourceDAO resourceDAO; + private ResourceVersionDAO resourceVersionDAO; + private AssociationDAO associationDAO; + private LogsDAO logsDAO; + + /** + * Datasource is set on all resources get from the repository. + */ + private DataSource dataSource; + + public Repository(DataSource dataSource) { + this.dataSource = dataSource; + resourceDAO = new ResourceDAO(); + resourceVersionDAO = new ResourceVersionDAO(); + associationDAO = new AssociationDAO(); + logsDAO = new LogsDAO(); + } + + /** + * Checks if a pure resource exists in the given path. + * + * @param path Path of a possible pure resource. + * @return ture if a resource exists in the given path. false otherwise. + */ + public boolean resourceExists(String path) throws RegistryException { + + String purePath = RegistryUtils.getPureResourcePath(path); + + return resourceDAO.resourceExists(purePath); + } + + /** + * Gets the pure resource referred by the given path. If purePath referes to a specific version of + * the resource, this gives the refered version. If path does not contain version information, + * this gives the current version of the resource. + * + * @param path Path of a "pure" resource. Path should map to an actual resource stored + * in the database. Paths refering to virtual resource are not handled (e.g. /c1/r1;comments). + * @return Resource refered by the given path. Resource can be a file or a collection. + */ + public Resource get(String path) throws RegistryException { + + String purePath = RegistryUtils.getPureResourcePath(path); + + String resourceID = ResourceDAO.getResourceID(purePath); + if (resourceID == null) { + return null; + } + + if (!AuthorizationUtils.authorize(resourceID, ActionConstants.GET)) { + String msg = "User " + CurrentSession.getUser() + " is not authorized to " + + "read the resource " + purePath + "."; + log.error(msg); + throw new AuthorizationFailedException(msg); + } + + Resource resource = resourceDAO.get(purePath); + ((ResourceImpl) resource).setDataSource(dataSource); + + return resource; + } + + public Collection get(String path, int start, int pageLen) throws RegistryException { + String purePath = RegistryUtils.getPureResourcePath(path); + + String resourceID = ResourceDAO.getResourceID(purePath); + if (resourceID == null) { + return null; + } + + if (!AuthorizationUtils.authorize(resourceID, ActionConstants.GET)) { + String msg = "User " + CurrentSession.getUser() + " is not authorized to " + + "read the resource " + purePath + "."; + log.error(msg); + throw new AuthorizationFailedException(msg); + } + + CollectionImpl resource = resourceDAO.get(purePath, start, pageLen); + resource.setDataSource(dataSource); + + return resource; + } + + /** + * Adds or updates the resource in the given path with the given resource. Put is executed if + * the current user has authorization to do so. Below is the method of evaluating + * authorizations. + * <p/> + * <ul> + * <li> user should have WRITE permissions for the resource, if he wants to update the + * resource.</li> + * <li>user should habe WRITE permissions for the parent of the new resource, if he wants to + * add a new resource.</li> + * </ul> + * + * @param path Path of the resource to be added or updated. Path should only refer to current + * version a pure resource. i.e. Path should not contain any version information as it is + * impossible to add or update old versions. + * @param resource Resource to be added or updated. + */ + public void put(String path, Resource resource) throws RegistryException { + + String purePath = RegistryUtils.getPureResourcePath(path); + + String resourceID; + if ((resourceID = ResourceDAO.getResourceID(purePath)) != null) { + + // resource already exists. try to update the resource + update(resourceID, purePath, resource); + + if (((ResourceImpl) resource).isVersionableChange()) { + resourceDAO.markDirty(resourceID); + } + + } else { + + // resource does not exists. add the resource. + add(purePath, resource); + + String parentPath = RegistryUtils.getParentPath(purePath); + resourceDAO.markDirtyByPath(parentPath); + } + + // all the ascendant collections of this resource gets modified. that is, if snapshot are + // created for those collections, all such snapshots get invalid. + invalidateParentSnapshots(path); + } + + /** + * Creates a resource with the content imported from the source URL and metadata extracted from + * the given metadata resource instance. Then the created resource is put to the registry using + * the Repository.put() method. + * + * @param path Path to put the resource + * @param sourceURL URL to import resource content + * @param metadata Metadata for the new resource is extracted from this metadata resource + * @return Actual path where the new resource is stored in the registry + * @throws RegistryException for all exceptional scenarios + */ + public String importResource(String path, String sourceURL, Resource metadata) + throws RegistryException { + + String purePath = RegistryUtils.getPureResourcePath(path); + + URL url; + try { + url = new URL(sourceURL); + } catch (MalformedURLException e) { + String msg = "Given source URL is not valid."; + throw new RegistryException(msg, e); + } + + try { + URLConnection uc = url.openConnection(); + InputStream in = uc.getInputStream(); +// resource.setPath(purePath); + String mediaType = metadata.getMediaType(); + if (mediaType == null) + mediaType = uc.getContentType(); + metadata.setMediaType(mediaType); + metadata.setDescription(metadata.getDescription()); + metadata.setContentStream(in); + put(purePath, metadata); + + } catch (IOException e) { + + String msg = "Could not read from the given URL: " + sourceURL; + throw new RegistryException(msg, e); + } + + String parentPath = RegistryUtils.getParentPath(purePath); + resourceDAO.markDirtyByPath(parentPath); + + return purePath; + } + + /** + * Deletes the pure resource refered by the path. + * + * @param path path Path of the resource deleted. Path should only refer to current + * version a pure resource. i.e. Path should not contain any version information as it is + * impossible to delete old versions. + */ + public void delete(String path) throws RegistryException { + + path = RegistryUtils.getPureResourcePath(path); + + String resourceID = ResourceDAO.getResourceID(path); + if (resourceID == null) { + String msg = "Failed to delete resource " + path + ". Resource does not exist."; + log.error(msg); + throw new RegistryException(msg); + } + + if (!AuthorizationUtils.authorize(resourceID, ActionConstants.DELETE)) { + String msg = "User " + CurrentSession.getUser() + " is not authorized to " + + "delete the resource " + path + "."; + log.error(msg); + throw new AuthorizationFailedException(msg); + } + + String parentPath = RegistryUtils.getParentPath(path); + + // parent collection gets dirty when a resource is deleted from it + resourceDAO.markDirtyByPath(parentPath); + + resourceDAO.deleteSubtree(resourceID); + + invalidateParentSnapshots(path); + } + + /** + * Renames the resource at oldPath with the given newName. If oldPath is + * "/projects/esb/config.xml" and newName is "synapse.xml" then the new path of the resource + * will be "/projects/esb/synapse.xml". If the renamed resource is a collection, paths of + * all its desendants will also be changed. + * + * @param oldPath Pure path of the resource to be renamed. + * @param newName New name for the resource. Name should not contain "/". + * @return New path of the resource. + * @throws RegistryException + */ + public String rename(String oldPath, String newName) throws RegistryException { + + oldPath = RegistryUtils.getPureResourcePath(oldPath); + + if (!newName.startsWith(RegistryConstants.PATH_SEPARATOR)) { + // relative URL + String oldDir = + oldPath.substring(0, oldPath.lastIndexOf(RegistryConstants.PATH_SEPARATOR) + 1); + newName = oldDir + newName; + } + + String resourceID = ResourceDAO.getResourceID(oldPath); + resourceDAO.setPath(resourceID, newName); + + // we don't support browsing previous versions (snapshots) of resources after renaming + // them currently + resourceVersionDAO.removeSnapshotsOfResource(resourceID); + + List<String> childIDs = resourceDAO.getChildIDs(resourceID); + Iterator<String> iChild = childIDs.iterator(); + while (iChild.hasNext()) { + String childID = iChild.next(); + renameChildren(childID, newName); + } + AssociationDAO.copyAssociations(oldPath ,newName); + + return newName; + } + + /** + * Moves the resource at oldPath to the newPath. If the resource is a collection, all its + * descendant resources will also be moved. + * + * @param oldPath Path of a existing resource + * @param newPath New path of the resource + * @return the actual new path + * @throws RegistryException + */ + public String move(String oldPath, String newPath) throws RegistryException { + + // we are implementing move as copying the resource to the new path and deleting the old + // resource. therefore, the moved resource will be threated as a new resource (i.e without + // a version hostory. but the resource at old path (which is deleted) has its version + // hostory. so it is possible to restore the parent collection of old path and get old + // versions of that resource. + + copy(oldPath, newPath); + + // once the resource is moved all associations with the old resource has to be reassociated + // with the new resource + associationDAO.replaceAssociations(oldPath, newPath); + + delete(oldPath); + return newPath; + } + + public String copy(String sourcePath, String targetPath) throws RegistryException { + + sourcePath = RegistryUtils.getPureResourcePath(sourcePath); + targetPath = RegistryUtils.getPureResourcePath(targetPath); + + ResourceImpl resource = (ResourceImpl) get(sourcePath); + final String newID = UUIDGenerator.generateUUID(); + resource.setId(newID); + put(targetPath, resource); + + String resourceID = ResourceDAO.getResourceID(sourcePath); + List<String> childIDs = resourceDAO.getChildIDs(resourceID); + Iterator<String> iChild = childIDs.iterator(); + while (iChild.hasNext()) { + String childID = iChild.next(); + copy(sourcePath, targetPath, childID); + } + + CommentsDAO.copyComments(sourcePath, newID); + TagsDAO.copyTags(resourceID, newID); + RatingsDAO.copyRatings(resourceID, newID); + AssociationDAO.copyAssociations(sourcePath ,targetPath); + return targetPath; + } + + private void copy(String sourcePath, String targetPath, String resourceID) + throws RegistryException { + + String resourcePath = resourceDAO.getResourcePath(resourceID); + ResourceImpl resource = (ResourceImpl) get(resourcePath); + String newId = UUIDGenerator.generateUUID(); + resource.setId(newId); + + String targetPathForThisResource = targetPath + resourcePath.substring(sourcePath.length()); + put(targetPathForThisResource, resource); + + List<String> childIDs = resourceDAO.getChildIDs(resourceID); + Iterator<String> iChild = childIDs.iterator(); + while (iChild.hasNext()) { + String childID = iChild.next(); + copy(sourcePath, targetPath, childID); + } + + CommentsDAO.copyComments(resourcePath, newId); + TagsDAO.copyTags(resourceID, newId); + RatingsDAO.copyRatings(resourceID, newId); + AssociationDAO.copyAssociations(resourcePath ,targetPathForThisResource); + } + + private void add(String path, Resource resource) throws RegistryException { + + // first add all non-existing parent collections. note that whether the user has + // permission to add this resource depends on the permissions of the nearest ascendant. + + String parentPath = RegistryUtils.getParentPath(path); + + // first, let's check if there is a parent for this resource. we do this to speed up the + // common use case where new resources are added to an existing parent. + String parentID = ResourceDAO.getResourceID(parentPath); + if (parentID == null) { + + // no parent exists for this the new resource. so we have to add all missing + // ancestor collections. this operation may be bit slow. but we ignore that as this + // is not very frequent. + addParents(path); + parentID = ResourceDAO.getResourceID(parentPath); + } + + if (!AuthorizationUtils.authorize(parentID, ActionConstants.PUT)) { + String msg = "Failed to add new resource " + path + ". User " + + CurrentSession.getUser() + " is not authorized to update " + + "the parent collection " + parentPath + "."; + log.error(msg); + throw new AuthorizationFailedException(msg); + } + + // then add the new resource/collection + logsDAO.addLog(path, CurrentSession.getUser(), LogEntry.ADD, null); + resourceDAO.add(path, parentID, (ResourceImpl) resource); + + // set authorizations for the newly added resource + AuthorizationUtils.copyAuthorizations(parentID, resource.getId()); + } + + private void invalidateParentSnapshots(String path) throws RegistryException { + + if (RegistryConstants.ROOT_PATH.equals(path)) { + return; + } + + String parentPath = RegistryUtils.getParentPath(path); + + resourceDAO.invalidateCurrentSnapshot(RegistryConstants.ROOT_PATH); + + if (RegistryConstants.ROOT_PATH.equals(parentPath)) { + return; + } + + String[] parts = parentPath.split(RegistryConstants.PATH_SEPARATOR); + + String currentPath = RegistryConstants.ROOT_PATH + parts[1]; + resourceDAO.invalidateCurrentSnapshot(currentPath); + + for (int i = 2; i < parts.length; i++) { + + currentPath = currentPath + RegistryConstants.PATH_SEPARATOR + parts[i]; + resourceDAO.invalidateCurrentSnapshot(currentPath); + } + } + + private void update(String resourceID, String path, Resource resource) + throws RegistryException { + + // resources are referred exclusively by the resource ID in the database. API users may + // create new resources and put them to existing paths. In that case, we have to set the + // ID of the existing resource, before giving it the database layer. + ((ResourceImpl) resource).setId(resourceID); + + if (!AuthorizationUtils.authorize(resourceID, ActionConstants.PUT)) { + String msg = "Resource update failed. User " + CurrentSession.getUser() + + " is not authorized to update the resource " + path + "."; + log.error(msg); + throw new AuthorizationFailedException(msg); + } + + logsDAO.addLog(path, CurrentSession.getUser(), LogEntry.UPDATE, null); + resourceDAO.update(resourceID, (ResourceImpl) resource); + + } + + /** + * Adds all non-existent collections of the given path starting from the root. Note that we + * are not using recursive method call here to avoid possible stack overflaws due to deep + * trees. + * <p/> + * Start from the root and check each ancestor collection exists. If we find any ancestor + * "resource" we can give this up, as resources cannot contain other collcetions or resources. + * When we find the first missing collection, we have to check whether the user has PUT + * permission for the parent of that collection. If user does, add a new collection. + * <p/> + * Now we don't have to worry about permissions anymore. Because authorizations are copied + * from parent to child, user can add all other required resources. + * + * @param path Path of which all non-existent collections are added. + * @throws RegistryException If any ancestor of the given path is a resource. + */ + private void addParents(String path) throws RegistryException { + + String parentPath = RegistryUtils.getParentPath(path); + + String[] parts = parentPath.split(RegistryConstants.PATH_SEPARATOR); + + String idOfLastExistingParent = null; + String currentPath = RegistryConstants.ROOT_PATH + parts[1]; + for (int i = 2; i < parts.length + 1; i++) { + + if (idOfLastExistingParent == null) { + + int resourceType = resourceDAO.getResourceType(currentPath); + if (resourceType == ResourceDAO.NULL) { + + String pathOfLastParent = RegistryUtils.getParentPath(currentPath); + idOfLastExistingParent = ResourceDAO.getResourceID(pathOfLastParent); + + if (!AuthorizationUtils.authorize( + idOfLastExistingParent, ActionConstants.PUT)) { + String msg = "Failed to add new resource. User " + + CurrentSession.getUser() + " does not have authorization to " + + "update the collection " + pathOfLastParent + "."; + log.error(msg); + throw new RegistryException(msg); + } + + CollectionImpl collection = new CollectionImpl(); + logsDAO.addLog(currentPath, CurrentSession.getUser(), LogEntry.ADD, null); + resourceDAO.add(currentPath, idOfLastExistingParent, collection); + + AuthorizationUtils.copyAuthorizations(idOfLastExistingParent, collection.getId()); + + } else if (resourceType == ResourceDAO.RESOURCE) { + + String msg = "Failed to add new resource. " + currentPath + " is a non-collection " + + "ancestor located in the given new resource path."; + log.error(msg); + throw new RegistryException(msg); + } + + } else { + + String currentParentPath = RegistryUtils.getParentPath(currentPath); + String currentParentID = ResourceDAO.getResourceID(currentParentPath); + + CollectionImpl collection = new CollectionImpl(); + logsDAO.addLog(currentPath, CurrentSession.getUser(), LogEntry.ADD, null); + resourceDAO.add(currentPath, currentParentID, collection); + + AuthorizationUtils.copyAuthorizations(idOfLastExistingParent, collection.getId()); + + } + + if (i < parts.length) { + currentPath = currentPath + RegistryConstants.PATH_SEPARATOR + parts[i]; + } + } + } + + private void renameChildren(String resourceID, String newParentPath) throws RegistryException { + + String resourcePath = resourceDAO.getResourcePath(resourceID); + String newPath = newParentPath + resourcePath.substring( + resourcePath.lastIndexOf(RegistryConstants.PATH_SEPARATOR), resourcePath.length()); + + resourceDAO.setPath(resourceID, newPath); + + // we don't support browsing previous versions (snapshots) of resources after renaming + // them currently + resourceVersionDAO.removeSnapshotsOfResource(resourceID); + + List<String> childIDs = resourceDAO.getChildIDs(resourceID); + Iterator<String> iChild = childIDs.iterator(); + while (iChild.hasNext()) { + String childID = iChild.next(); + renameChildren(childID, newPath); + } + AssociationDAO.copyAssociations(resourcePath ,newPath); + } +} _______________________________________________ Mashup-dev mailing list [email protected] http://wso2.org/cgi-bin/mailman/listinfo/mashup-dev
