SolutionRepository.java
| Index Score | ||
|---|---|---|
![]() |
![]() |
com.pentaho.repository.dbbased.solution |
![]() |
![]() |
Pentaho |
View: Reasons, Metrics, Source Code
These are the metrics that contribute to the Enerjy Score for this file, ranked by impact. So the metrics listed at the top influence the score to a greater extent that the metrics listed at the bottom.
/*
* Copyright 2005 Pentaho Corporation. All rights reserved.
* This software was developed by Pentaho Corporation and is provided under the terms
* of the Mozilla Public License, Version 1.1, or any later version. You may not use
* this file except in compliance with the license. If you need a copy of the license,
* please go to http://www.mozilla.org/MPL/MPL-1.1.txt. The Original Code is the Pentaho
* BI Platform. The Initial Developer is Pentaho Corporation.
*
* Software distributed under the Mozilla Public License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. Please refer to
* the license for the specific language governing your rights and limitations.
*
* @created Jun 21, 2005
* @author James Dixon
*
*/
package com.pentaho.repository.dbbased.solution;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Node;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.pentaho.core.repository.ISolutionRepository;
import org.pentaho.core.repository.RepositoryException;
import org.pentaho.core.repository.SolutionRepositoryBase;
import org.pentaho.core.session.IPentahoSession;
import org.pentaho.core.solution.IActionSequence;
import org.pentaho.core.solution.ISolutionFile;
import org.pentaho.core.solution.SequenceDefinition;
import org.pentaho.core.solution.SolutionReposUtil;
import org.pentaho.core.solution.SolutionReposUtil.ISolutionFilter;
import org.pentaho.core.system.IPentahoInitializer;
import org.pentaho.core.system.PentahoSystem;
import org.pentaho.core.util.XmlHelper;
import org.pentaho.messages.Messages;
import org.pentaho.repository.HibernateUtil;
import org.pentaho.repository.filebased.solution.FileInfo;
import org.pentaho.util.FileHelper;
import com.pentaho.repository.subscribe.ISubscriptionRepository;
import com.pentaho.security.AcegiPermissionMgr;
import com.pentaho.security.IPermissionMask;
import com.pentaho.security.IPermissionRecipient;
import com.pentaho.security.PentahoAccessControlException;
import com.pentaho.security.SecurityUtils;
import com.pentaho.security.SimplePermissionMask;
import com.pentaho.security.SimpleRole;
import com.pentaho.security.SimpleSession;
import com.pentaho.security.acls.IAclHolder;
import com.pentaho.security.acls.IAclPublisher;
import com.pentaho.security.acls.PentahoAclEntry;
import com.pentaho.security.acls.voter.IAclVoter;
/**
* @author William Seyler
*/
public class SolutionRepository extends SolutionRepositoryBase implements SolutionReposUtil.ISolutionFilter,
SolutionReposUtil.ISolutionAttributeContributor, IPentahoInitializer {
private static final long serialVersionUID = -8270135463210017284L;
private static final String BREAD_CRUMBS_TAG = "breadcrumbs/"; //$NON-NLS-1$
// private String rootFile;
private String repositoryName;
private RepositoryFile rootDirectory;
private byte[] lock = new byte[0];
private boolean repositoryInit = false;
public SolutionRepository() {
init();
}
public void init() {
if (!repositoryInit) {
super.init();
String reposName = PentahoSystem.getSystemSetting("solution-repository/db-repository-name", null); //$NON-NLS-1$
if (reposName != null) {
setRepositoryName(reposName);
logger.info(Messages.getString("SolutionRepository.WARN_0002_USING_SOLUTION_NAME", getRepositoryName())); //$NON-NLS-1$
} else {
logger.info(Messages.getString("SolutionRepository.WARN_0001_UNDEFINED_SOLUTION_NAME")); //$NON-NLS-1$
}
RepositoryFile root = (RepositoryFile) getRootFolder();
if (root == null) {
String path = PentahoSystem.getApplicationContext().getSolutionPath(""); //$NON-NLS-1$
loadSolutionFromFileSystem(getSession(), path, true);
root = (RepositoryFile) getRootFolder();
}
repositoryInit = true;
}
}
public IActionSequence getActionSequence(String solutionName, String actionPath, String sequenceName,
int localLoggingLevel, int actionOperation) {
String action = buildDirectoryPath(solutionName, actionPath, sequenceName);
if (action == null || action.length() == 0) {
error(Messages.getErrorString("SolutionRepository.ERROR_0008_ACTION_SEQUENCE_NAME_INVALID"));
return null;
}
Document actionSequenceDocument = getSolutionDocument(action, actionOperation);
if (actionSequenceDocument == null) {
return null;
}
IActionSequence actionSequence = SequenceDefinition.ActionSequenceFactory(actionSequenceDocument, sequenceName,
actionPath, solutionName, this, PentahoSystem.getApplicationContext(), localLoggingLevel);
if (actionSequence == null) {
return null;
}
return actionSequence;
}
public boolean hasAccess(IPermissionRecipient permRecipient, ISolutionFile aFile, int actionOperation) {
AcegiPermissionMgr permissionMgr = AcegiPermissionMgr.instance();
IPermissionMask permissionMask = mapOperationToPermissionMask(actionOperation);
return permissionMgr.hasPermission(permRecipient, permissionMask, aFile);
}
/**
* TODO mlowery Need to throw exception if unauthorized. (If there ever is a READ_PERMISSIONS permission.
*/
public boolean hasAccess(ISolutionFile aFile, int actionOperation) {
return hasAccess(new SimpleSession(getSession()), aFile, actionOperation);
}
public boolean isPentahoAdministrator() {
return SecurityUtils.isPentahoAdministrator(getSession());
}
/**
* TODO mlowery This method trusts that actionOperation is what the caller really wants to do???
*/
public Document getSolutionDocument(String documentPath, int actionOperation) {
RepositoryFile file = (RepositoryFile) getRepositoryObjectFromCache(documentPath);
if (file == null) { // Not in cache... go to the solution repository
file = (RepositoryFile) getFileByPath(documentPath);
if (file != null) {
putRepositoryObjectInCache(documentPath, file);
} else {
logger.warn(Messages.getString("SolutionRepository.WARN_0004_DOCUMENT_NOT_FOUND", documentPath));
return null; //If it's still null then it doesn't exist
}
}
if (!hasAccess(file, actionOperation)) {
if (logger.isDebugEnabled()) {
logger.debug(Messages.getString(
"SolutionRepository.ACCESS_DENIED", documentPath, Integer.toString(actionOperation))); //$NON-NLS-1$
}
error(Messages.getString("SolutionRepository.ACCESS_DENIED", documentPath, Integer.toString(actionOperation))); //$NON-NLS-1$
return null;
}
Document document = null;
if (file.getData() != null) {
try {
document = XmlHelper.getDocFromString(new String(file.getData()));
} catch (Throwable t) {
error(Messages.getErrorString("SolutionRepository.ERROR_0017_INVALID_XML_DOCUMENT", documentPath), t); //$NON-NLS-1$
return null;
}
} else {
error(Messages.getErrorString("SolutionRepository.ERROR_0019_NO_DATA_IN_FILE", file.fileName)); //$NON-NLS-1$
return null;
}
if (document == null && file != null && file.getData() != null) {
// the document exists but cannot be parsed
error(Messages.getErrorString("SolutionRepository.ERROR_0009_INVALID_DOCUMENT", documentPath)); //$NON-NLS-1$
return null;
}
localizeDoc(document, file);
return document;
}
public void reloadSolutionRepository(IPentahoSession localSession, int localLoggingLevel) {
this.loggingLevel = localLoggingLevel;
String path = PentahoSystem.getApplicationContext().getSolutionPath(""); //$NON-NLS-1$
DbRepositoryClassLoader.clearResourceCache();
loadSolutionFromFileSystem(localSession, path, true);
}
private void loadSolutionPath(String solutionName, String path, int localLoggingLevel) {
this.loggingLevel = localLoggingLevel;
if (isCachingAvailable()) {
String localDirStr = buildDirectoryPath(solutionName, path, null);
Document repository = DocumentHelper.createDocument();
Element rootNode = null;
RepositoryFile directory = (RepositoryFile) getFileByPath(localDirStr);
if (directory.isRoot()) {
rootNode = repository.addElement("repository"); //$NON-NLS-1$
Document indexDoc = getSolutionDocument(directory.getFullPath() + RepositoryFile.SEPARATOR
+ SolutionRepositoryBase.INDEX_FILENAME, ISolutionRepository.ACTION_EXECUTE);
if (indexDoc != null) {
addIndexToRepository(indexDoc, directory, rootNode, path, solutionName);
}
processDir(rootNode, directory, solutionName, ISolutionRepository.ACTION_EXECUTE, BROWSE_DEPTH);
} else {
Element filesNode = repository.addElement("files"); //$NON-NLS-1$
rootNode = filesNode.addElement("file"); //$NON-NLS-1$
rootNode.addAttribute("type", FileInfo.FILE_TYPE_FOLDER); //$NON-NLS-1$
rootNode.addElement("path").setText(path != null ? path : ""); //$NON-NLS-1$//$NON-NLS-2$
Document indexDoc = getSolutionDocument(directory.getFullPath() + RepositoryFile.SEPARATOR
+ SolutionRepositoryBase.INDEX_FILENAME, ISolutionRepository.ACTION_EXECUTE);
if (indexDoc != null) {
addIndexToRepository(indexDoc, directory, rootNode, path, solutionName);
}
processDir(rootNode, directory, solutionName, ISolutionRepository.ACTION_EXECUTE, BROWSE_DEPTH);
filesNode.addElement(LOCATION_ATTR_NAME).setText(getPathNames(solutionName, path) + RepositoryFile.SEPARATOR);
}
putRepositoryObjectInCache(localDirStr + getLocale().toString(), repository);
}
}
private String buildDirectoryPath(String solution, String path, String action) {
String localDirStr = repositoryName;
if (solution != null && solution.length() > 0) {
localDirStr += solution;
if (path != null && path.length() > 0) {
localDirStr += RepositoryFile.SEPARATOR;
localDirStr += path;
}
}
if (action != null && action.length() > 0) {
String seperator = new String() + RepositoryFile.SEPARATOR;
if (!localDirStr.endsWith(seperator)) {
localDirStr += RepositoryFile.SEPARATOR;
}
localDirStr += action;
}
return localDirStr;
}
private Document getCachedSolutionDocument(String solutionName, String pathName, int actionOperation) {
if (actionOperation == ISolutionRepository.ACTION_EXECUTE) {
String localDirStr = buildDirectoryPath(solutionName, pathName, null);
Object cachedRepo = this.getRepositoryObjectFromCache(localDirStr + getLocale().toString());
if (cachedRepo == null) {
loadSolutionPath(solutionName, pathName, this.loggingLevel);
cachedRepo = this.getRepositoryObjectFromCache(localDirStr + getLocale().toString());
}
return (Document) cachedRepo;
} else {
return null;
}
}
/*
* private void processDir(Element parentNode, RepositoryFile parentDir, String solutionId, int actionOperation) {
* processDir(parentNode, parentDir, solutionId, actionOperation, true); }
*/
private void processDir(Element parentNode, RepositoryFile parentDir, String solutionId, int actionOperation,
int recurseLevels) {
if (recurseLevels <= 0) {
return;
}
RepositoryFile[] files = parentDir.listRepositoryFiles();
// first process the directories
for (int idx = 0; idx < files.length; idx++) {
if (!files[idx].isDirectory()) {
String fileName = files[idx].getFileName();
if (fileName.equals("Entries") || fileName.equals("Repository") || fileName.equals("Root")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
// ignore any CVS files
continue;
}
if (fileName.toLowerCase().endsWith(".url")) { //$NON-NLS-1$
if (hasAccess(files[idx], actionOperation)) {
addUrlToRepository(files[idx], parentNode);
}
}
if (!fileName.toLowerCase().endsWith(".xaction") && !fileName.toLowerCase().endsWith(".xml")) { //$NON-NLS-1$ //$NON-NLS-2$
// ignore any non-XML files
continue;
}
if (fileName.toLowerCase().equals(SolutionRepositoryBase.INDEX_FILENAME)) {
// index.xml files are handled in the directory loop below
continue;
}
String path = getSolutionPath(files[idx]);
if (fileName.toLowerCase().endsWith(".xaction")) { //$NON-NLS-1$
// create an action sequence document from this
info(Messages.getString("SolutionRepository.DEBUG_ADDING_ACTION", fileName)); //$NON-NLS-1$
IActionSequence actionSequence = getActionSequence(solutionId, path, fileName, loggingLevel, actionOperation);
if (actionSequence == null) {
if ((solutionId == null || solutionId.length() == 0) && (path == null || path.length() == 0)) {
info(Messages.getString("SolutionRepository.INFO_0008_NOT_ADDED", fileName)); //$NON-NLS-1$
} else {
error(Messages.getErrorString("SolutionRepository.ERROR_0006_INVALID_SEQUENCE_DOCUMENT", fileName)); //$NON-NLS-1$
}
} else {
addToRepository(actionSequence, parentNode, files[idx]);
}
}
}
}
for (int idx = 0; idx < files.length; idx++) {
if (files[idx].isDirectory()
&& (!files[idx].getFileName().equalsIgnoreCase("system")) && (!files[idx].getFileName().equalsIgnoreCase("CVS")) && (!files[idx].getFileName().equalsIgnoreCase(".svn"))) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
Element dirNode = parentNode.addElement("file"); //$NON-NLS-1$
dirNode.addAttribute("type", FileInfo.FILE_TYPE_FOLDER); //$NON-NLS-1$
contributeAttributes(files[idx], dirNode);
// TODO read this from the directory index file
String thisSolution;
String path = getSolutionPath(files[idx]);
if (solutionId == null) {
thisSolution = getSolutionId(files[idx]);
} else {
thisSolution = solutionId;
dirNode.addElement("path").setText(path); //$NON-NLS-1$
}
Document indexDoc = getSolutionDocument(files[idx].getFullPath() + RepositoryFile.SEPARATOR
+ SolutionRepositoryBase.INDEX_FILENAME, actionOperation);
if (indexDoc != null) {
addIndexToRepository(indexDoc, files[idx], dirNode, path, thisSolution);
} else {
dirNode.addAttribute("visible", "false"); //$NON-NLS-1$ //$NON-NLS-2$
String dirName = files[idx].getFileName();
dirNode.addAttribute("name", XmlHelper.encode(dirName)); //$NON-NLS-1$
dirNode.addElement("title").setText(dirName); //$NON-NLS-1$
}
processDir(dirNode, files[idx], thisSolution, actionOperation, recurseLevels - 1);
}
}
}
private String getSolutionId(RepositoryFile file) {
String path = file.getFullPath();
if (path.length() < repositoryName.length()) {
return ""; //$NON-NLS-1$
}
path = path.substring(repositoryName.length()); // Strip off the root
// directory
// Strip off the fileName if any
if (path.indexOf(RepositoryFile.SEPARATOR) != -1) {
path = path.substring(0, path.indexOf(RepositoryFile.SEPARATOR));
}
return path;
}
private String getSolutionPath(RepositoryFile file) {
String path = file.getFullPath();
try {
path = path.substring(repositoryName.length()); // Strip off the
// root
// directory
// Strip off the filename if there is one
if (!file.isDirectory()) {
path = path.substring(0, path.lastIndexOf(RepositoryFile.SEPARATOR));
}
// Strip off the solution folder and the following / if any else we
// know we have a solution folder and return empty String
if (path.indexOf(RepositoryFile.SEPARATOR) != -1) {
path = path.substring(path.indexOf(RepositoryFile.SEPARATOR) + 1);
} else {
return EMPTY_STR;
}
} catch (StringIndexOutOfBoundsException ex) {
return EMPTY_STR;
}
return path;
}
private void addIndexToRepository(Document indexDoc, RepositoryFile directoryFile, Element directoryNode,
String path, String solution) {
if (!directoryFile.isDirectory()) {
return;
}
// TODO see if there is a localized attribute file for the current
// locale
String dirName = getValue(indexDoc, "/index/name", directoryFile.getFileName().replace('_', ' ')); //$NON-NLS-1$
String description = getValue(indexDoc, "/index/description", EMPTY_STR); //$NON-NLS-1$
String iconPath = getValue(indexDoc, "/index/icon", EMPTY_STR); //$NON-NLS-1$
String displayType = getValue(indexDoc, "/index/display-type", "icons"); //$NON-NLS-1$ //$NON-NLS-2$
boolean visible = getValue(indexDoc, "/index/visible", "false").equalsIgnoreCase("true"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
path = XmlHelper.encode(path);
String name = XmlHelper.encode(directoryFile.getFileName());
// We want to cache the localized document name if we don't already have it
if (directoryFile.isDirectory() && getPathNames(solution, path) == null) {
cacheLocalizedDirectoryName(dirName, directoryFile, solution, path);
}
directoryNode.addAttribute("name", name); //$NON-NLS-1$
directoryNode.addElement("title").setText(dirName); //$NON-NLS-1$
directoryNode.addAttribute("path", path); //$NON-NLS-1$
directoryNode.addElement("description").setText(description); //$NON-NLS-1$
if (iconPath != null && !iconPath.equals("")) { //$NON-NLS-1$
String rolloverIconPath = null;
int rolloverIndex = iconPath.indexOf("|"); //$NON-NLS-1$
if (rolloverIndex > -1) {
rolloverIconPath = iconPath.substring(rolloverIndex + 1);
iconPath = iconPath.substring(0, rolloverIndex);
}
if (publishIcon(directoryFile.isDirectory() ? directoryFile.getFullPath() : directoryFile.retrieveParent()
.getFullPath(), iconPath)) {
directoryNode.addElement("icon").setText("getImage?image=icons/" + iconPath); //$NON-NLS-1$ //$NON-NLS-2$
} else {
directoryNode.addElement("icon").setText(iconPath); //$NON-NLS-1$
}
if (rolloverIconPath != null) {
if (publishIcon(directoryFile.isDirectory() ? directoryFile.getFullPath() : directoryFile.retrieveParent()
.getFullPath(), rolloverIconPath)) {
directoryNode.addElement("rollovericon").setText("getImage?image=icons/" + rolloverIconPath); //$NON-NLS-1$ //$NON-NLS-2$
} else {
directoryNode.addElement("rollovericon").setText(rolloverIconPath); //$NON-NLS-1$
}
}
}
Boolean visability = null;
boolean hasAccess = SecurityUtils.hasAccess(directoryFile, ISolutionRepository.ACTION_EXECUTE, getSession());
if (!hasAccess) {
visability = new Boolean(false);
} else {
visability = new Boolean(visible);
}
directoryNode.addAttribute("visible", visability.toString()); //$NON-NLS-1$
directoryNode.addAttribute("displaytype", displayType); //$NON-NLS-1$
if (solution != null && solution.length() > 0) {
directoryNode.addElement("solution").setText(solution); //$NON-NLS-1$
} else {
directoryNode.addElement("solution").setText(getSolutionId(directoryFile)); //$NON-NLS-1$
}
}
private void cacheLocalizedDirectoryName(String localizedPath, RepositoryFile directoryFile, String solution,
String path) {
if (directoryFile.isRoot()) { // We're done and have the final localized string in dirName
putRepositoryObjectInCache(BREAD_CRUMBS_TAG + buildDirectoryPath(solution, path, null), localizedPath);
} else { // We've got to process the name of the parent
String localizedAncestors = (String) getRepositoryObjectFromCache(BREAD_CRUMBS_TAG
+ directoryFile.retrieveParent().getFullPath());
if (localizedAncestors != null) { // The parents stuff was already cached
localizedPath = localizedAncestors + RepositoryFile.SEPARATOR + localizedPath;
putRepositoryObjectInCache(BREAD_CRUMBS_TAG + buildDirectoryPath(solution, path, null), localizedPath);
} else { // Now we've got to check to see if the parent has an index.xml
Document indexDoc = getSolutionDocument(directoryFile.retrieveParent().getFullPath() + RepositoryFile.SEPARATOR
+ SolutionRepositoryBase.INDEX_FILENAME, ISolutionRepository.ACTION_EXECUTE);
if (indexDoc == null) {
localizedPath = directoryFile.retrieveParent().getFileName() + RepositoryFile.SEPARATOR + localizedPath;
} else {
localizedPath = getValue(indexDoc,
"/index/name", directoryFile.retrieveParent().getFileName().replace('_', ' ')) + RepositoryFile.SEPARATOR + localizedPath; //$NON-NLS-1$
}
cacheLocalizedDirectoryName(localizedPath, (RepositoryFile) directoryFile.retrieveParent(), solution, path);
}
}
}
private void addUrlToRepository(RepositoryFile file, Element parentNode) {
String urlContent = new String(file.getData());
StringTokenizer tokenizer = new StringTokenizer(urlContent, "\n"); //$NON-NLS-1$
String url = null;
String title = file.getFileName();
String description = null;
String iconPath = null;
String target = null;
while (tokenizer.hasMoreTokens()) {
String line = tokenizer.nextToken();
int pos = line.indexOf('=');
if (pos > 0) {
String name = line.substring(0, pos);
String value = line.substring(pos + 1);
if ((value != null) && (value.length() > 0) && (value.charAt(value.length() - 1) == '\r')) {
value = value.substring(0, value.length() - 1);
}
if ("URL".equalsIgnoreCase(name)) { //$NON-NLS-1$
url = value;
}
if ("name".equalsIgnoreCase(name)) { //$NON-NLS-1$
title = value;
}
if ("description".equalsIgnoreCase(name)) { //$NON-NLS-1$
description = value;
}
if ("icon".equalsIgnoreCase(name)) { //$NON-NLS-1$
iconPath = value;
}
if ("target".equalsIgnoreCase(name)) { //$NON-NLS-1$
target = value;
}
}
}
if (url != null) {
// now create an entry for the database
Element dirNode = parentNode.addElement("file"); //$NON-NLS-1$
dirNode.addAttribute("type", FileInfo.FILE_TYPE_URL); //$NON-NLS-1$
dirNode.addElement("filename").setText(file.getFileName()); //$NON-NLS-1$
dirNode.addElement("title").setText(title); //$NON-NLS-1$
if (target != null) {
dirNode.addElement("target").setText(target); //$NON-NLS-1$
}
if (description != null) {
dirNode.addElement("description").setText(description); //$NON-NLS-1$
}
if (iconPath != null && !iconPath.equals("")) { //$NON-NLS-1$
String rolloverIconPath = null;
int rolloverIndex = iconPath.indexOf("|"); //$NON-NLS-1$
if (rolloverIndex > -1) {
rolloverIconPath = iconPath.substring(rolloverIndex + 1);
iconPath = iconPath.substring(0, rolloverIndex);
}
if (publishIcon(file.retrieveParent().getFullPath(), iconPath)) {
dirNode.addElement("icon").setText("getImage?image=icons/" + iconPath); //$NON-NLS-1$ //$NON-NLS-2$
} else {
dirNode.addElement("icon").setText(iconPath); //$NON-NLS-1$
}
if (rolloverIconPath != null) {
if (publishIcon(file.retrieveParent().getFullPath(), rolloverIconPath)) {
dirNode.addElement("rollovericon").setText("getImage?image=icons/" + rolloverIconPath); //$NON-NLS-1$ //$NON-NLS-2$
} else {
dirNode.addElement("rollovericon").setText(rolloverIconPath); //$NON-NLS-1$
}
}
}
dirNode.addElement("url").setText(url); //$NON-NLS-1$
dirNode.addAttribute("visible", "true"); //$NON-NLS-1$ //$NON-NLS-2$
dirNode.addAttribute("displaytype", FileInfo.FILE_DISPLAY_TYPE_URL); //$NON-NLS-1$
localizeDoc(dirNode, file);
}
}
private void addToRepository(IActionSequence actionSequence, Element parentNode, RepositoryFile file) {
Element dirNode = parentNode.addElement("file"); //$NON-NLS-1$
dirNode.addAttribute("type", FileInfo.FILE_TYPE_ACTIVITY); //$NON-NLS-1$
contributeAttributes(file, dirNode);
if (actionSequence.getSequenceName() == null || actionSequence.getSolutionPath() == null
|| actionSequence.getSolutionName() == null) {
error(Messages.getString("SolutionRepository.ERROR_0008_ACTION_SEQUENCE_NAME_INVALID")); //$NON-NLS-1$
return;
}
dirNode.addElement("filename").setText(actionSequence.getSequenceName()); //$NON-NLS-1$
dirNode.addElement("path").setText(actionSequence.getSolutionPath()); //$NON-NLS-1$
dirNode.addElement("solution").setText(actionSequence.getSolutionName()); //$NON-NLS-1$
String title = actionSequence.getTitle();
if (title == null) {
dirNode.addElement("title").setText(actionSequence.getSequenceName()); //$NON-NLS-1$
} else {
dirNode.addElement("title").setText(title); //$NON-NLS-1$
}
String description = actionSequence.getDescription();
if (description == null) {
dirNode.addElement("description"); //$NON-NLS-1$
} else {
dirNode.addElement("description").setText(description); //$NON-NLS-1$
}
String author = actionSequence.getAuthor();
if (author == null) {
dirNode.addElement("author"); //$NON-NLS-1$
} else {
dirNode.addElement("author").setText(author); //$NON-NLS-1$
}
String iconPath = actionSequence.getIcon();
if (iconPath != null && !iconPath.equals("")) { //$NON-NLS-1$
String rolloverIconPath = null;
int rolloverIndex = iconPath.indexOf("|"); //$NON-NLS-1$
if (rolloverIndex > -1) {
rolloverIconPath = iconPath.substring(rolloverIndex + 1);
iconPath = iconPath.substring(0, rolloverIndex);
}
if (publishIcon(file.retrieveParent().getFullPath(), iconPath)) {
dirNode.addElement("icon").setText("getImage?image=icons/" + iconPath); //$NON-NLS-1$ //$NON-NLS-2$
} else {
dirNode.addElement("icon").setText(actionSequence.getIcon()); //$NON-NLS-1$
}
if (rolloverIconPath != null) {
if (publishIcon(file.retrieveParent().getFullPath(), rolloverIconPath)) {
dirNode.addElement("rollovericon").setText("getImage?image=icons/" + rolloverIconPath); //$NON-NLS-1$ //$NON-NLS-2$
} else {
dirNode.addElement("rollovericon").setText(rolloverIconPath); //$NON-NLS-1$
}
}
}
String displayType = actionSequence.getResultType();
if ((displayType == null) || ("none".equalsIgnoreCase(displayType))) { //$NON-NLS-1$
// this should be hidden from users
dirNode.addAttribute("visible", "false"); //$NON-NLS-1$ //$NON-NLS-2$
} else {
dirNode.addAttribute("visible", "true"); //$NON-NLS-1$ //$NON-NLS-2$
dirNode.addAttribute("displaytype", displayType); //$NON-NLS-1$
}
ISubscriptionRepository subscriptionRepository = PentahoSystem.getSubscriptionRepository(this.getSession());
boolean subscribable = subscriptionRepository.getContentByActionReference(actionSequence.getSolutionName() + '/'
+ actionSequence.getSolutionPath() + '/' + actionSequence.getSequenceName()) != null;
dirNode.addElement("properties").setText("subscribable=" + Boolean.toString(subscribable)); //$NON-NLS-1$ //$NON-NLS-2$
}
private boolean publishIcon(String dirPath, String iconPath) {
String pathSeperator = new StringBuffer().append(RepositoryFile.SEPARATOR).toString();
if (!iconPath.startsWith(pathSeperator)) {
iconPath = pathSeperator + iconPath;
}
String iconRepositoryPath = dirPath + iconPath;
RepositoryFile iconSource = (RepositoryFile) getFileByPath(iconRepositoryPath);
if (iconSource != null) {
File tmpDir = getFile("system/tmp/icons", true); //$NON-NLS-1$
tmpDir.mkdirs();
File iconDestintation = new File(tmpDir.getAbsoluteFile() + File.separator + iconPath);
if (iconDestintation.exists()) {
iconDestintation.delete();
}
try {
FileOutputStream outputStream = new FileOutputStream(iconDestintation);
outputStream.write(iconSource.getData());
outputStream.flush();
outputStream.close();
} catch (FileNotFoundException e) {
// this one is not very likey
} catch (IOException e) {
}
return true;
} else {
return false;
}
}
public Document getSolutions(String solutionName, String pathName, int actionOperation, boolean visibleOnly) {
return getCachedSolutionDocument(solutionName, pathName, actionOperation);
}
private String getPathNames(String solution, String path) {
String key = BREAD_CRUMBS_TAG + buildDirectoryPath(solution, path, null);
return (String) getRepositoryObjectFromCache(key);
}
// TODO sbarkdull, refactor, this should either be private, or should be in the XmlHelper class (prefer 2nd)
// maybe rename getNodeTextOrDefault
public String getValue(Document doc, String xPath, String defaultValue) {
if (doc != null) {
Node node = doc.selectSingleNode(xPath);
if (node == null) {
return defaultValue;
}
return node.getText();
}
return defaultValue;
}
public Document getSolutionTree(int actionOperation) {
return getSolutionTree(actionOperation, this);
}
public Document getSolutionTree(int actionOperation, ISolutionFilter filter) {
Document document = DocumentHelper.createDocument();
getRootFolder();
if (!hasAccess(rootDirectory, actionOperation)) {
if (logger.isDebugEnabled()) {
logger.debug(Messages.getString(
"SolutionRepository.ACCESS_DENIED", rootDirectory.getFullPath(), Integer.toString(actionOperation))); //$NON-NLS-1$
}
return document; // Empty Document
}
Element root = document.addElement("tree"); //$NON-NLS-1$
SolutionReposUtil.processSolutionTree(root, rootDirectory, filter, actionOperation);
return document;
}
public Document getSolutionStructure(int actionOperation) {
Document document = DocumentHelper.createDocument();
getRootFolder();
Element root = document.addElement(ROOT_NODE_NAME).addAttribute(LOCATION_ATTR_NAME, rootDirectory.getFullPath());
SolutionReposUtil.processSolutionStructure(root, rootDirectory, this, actionOperation);
return document;
}
public String resetSolutionFromFileSystem(IPentahoSession pSession) {
try {
RepositoryFile solution = (RepositoryFile) getRootFolder();
if (solution != null) {
HibernateUtil.beginTransaction();
HibernateUtil.makeTransient(solution);
HibernateUtil.commitTransaction();
HibernateUtil.flushSession();
}
this.loadSolutionFromFileSystem(pSession, PentahoSystem.getApplicationContext().getSolutionPath(""), true); //$NON-NLS-1$
} catch (Exception e) {
return Messages.getString("SolutionRepository.ERROR_0013_RESET_FAILED", e.getLocalizedMessage()); //$NON-NLS-1$
}
return Messages.getString("SolutionRepository.INFO_0009_RESET_SUCCESS"); //$NON-NLS-1$
}
/** *************************** New Update DB Repository Classes and Methods ******************************* */
/**
* This method loads solution files and folders from the file system into the RDBMS repository.
*
* @param pSession
* Users' Session
* @param solutionRoot
* The file system root folder
* @param deleteOrphans
* Whether to delete stranded references from RDBMS repository
* @return List of orphans that were deleted - returns list of deleted solution files.
* @throws RepositoryException
* @author mbatchel
*/
public synchronized List loadSolutionFromFileSystem(IPentahoSession pSession, String solutionRoot,
boolean deleteOrphans) throws RepositoryException {
logger.info(Messages.getString("SolutionRepository.INFO_0001_BEGIN_LOAD_DB_REPOSITORY")); //$NON-NLS-1$
HibernateUtil.beginTransaction();
File solutionFile = new File(solutionRoot);
RepositoryFile solution = null;
try {
if (solutionFile.isDirectory()) {
Map reposFileStructure = this.getAllRepositoryModDates();
/*
* The fromBase and toBase are, for example: From Base: D:\japps\pentaho\my-solutions\solutions To Base:
* /solutions
*/
String fromBase = solutionFile.getCanonicalPath();
String toBase = (solutionFile.getName().charAt(0) == '/') ? solutionFile.getName()
: "/" + solutionFile.getName(); //$NON-NLS-1$
RepositoryUpdateHelper updateHelper = new RepositoryUpdateHelper(fromBase, toBase, reposFileStructure, this);
//
// Check to see if we're just doing a refresh...
//
InfoHolder checkBase = (InfoHolder) reposFileStructure.get(toBase);
if (checkBase != null) {
// It's there - we're refreshing
checkBase.touched = true;
// Get the solution object from Hibernate
solution = (RepositoryFile) getFileByPath(null); // Hibernate Query
updateHelper.createdOrRetrievedFolders.put(toBase, solution); // Store for later reference
} else {
solution = new RepositoryFile(solutionFile.getName(), null, null, solutionFile.lastModified()); // Create
// entry
// Put the created folder into the created map for later use
updateHelper.createdOrRetrievedFolders.put(toBase, solution); // Store for later reference
logger.info(Messages.getString("SolutionRepository.INFO_0002_UPDATED_FOLDER", solution.getFullPath())); //$NON-NLS-1$
}
repositoryName = solution.getFullPath() + RepositoryFile.SEPARATOR;
// Find and record changes and updates
recurseCheckUpdatedFiles(updateHelper, solutionFile);
//
// The following lines are order dependent
//
// Handle updated Files and Folders
updateHelper.processUpdates();
// Handle added folders and files
updateHelper.processAdditions();
// Save solution state
HibernateUtil.makePersistent(solution);
// Process deletions
List deletions = updateHelper.processDeletions(deleteOrphans);
// Publish ACLs
IAclPublisher aclPublisher = PentahoSystem.getAclPublisher(pSession);
if (aclPublisher != null) {
aclPublisher.publishDefaultAcls(solution);
}
// Tell Hibernate we're ready for a commit - we're done now
HibernateUtil.commitTransaction();
HibernateUtil.flushSession();
// The next two lines were from the old code
resetRepository(); // Clear the cache of old stuff
logger.info(Messages.getString("SolutionRepository.INFO_0003_END_LOAD_DB_REPOSITORY")); //$NON-NLS-1$
return deletions;
} else {
throw new RepositoryException(Messages.getString(
"SolutionRepository.ERROR_0012_INVALID_SOLUTION_ROOT", solutionRoot)); //$NON-NLS-1$
}
} catch (HibernateException hibernateException) {
// re-throw exception so that it abandons the process
try {
HibernateUtil.rollbackTransaction();
} catch (HibernateException ignored) {
logger.error("SolutionRepository.ERROR_0011_TRANSACTION_FAILED", ignored); //$NON-NLS-1$
}
throw new RepositoryException(hibernateException);
} catch (IOException ex) {
// re-throw exception so that it abandons the process
throw new RepositoryException(ex);
}
}
/**
* This method builds up lists of the files modified (based on date/time), new folders, and new files.
*
* @param reposFileStructure
* Map of what's currently in the DB repository
* @param solutionFile
* The folder to begin working through
* @param updatedFiles
* List of files updated
* @param newFolders
* List of new folders
* @param newFiles
* List of new files
* @throws IOException
* @author mbatchel
*/
private void recurseCheckUpdatedFiles(RepositoryUpdateHelper updateHelper, File solutionFile) throws IOException {
File[] files = solutionFile.listFiles();
for (int i = 0; i < files.length; i++) {
File aFile = files[i];
if (aFile.isDirectory()) {
String directoryName = aFile.getName();
if (!SolutionReposUtil.ignoreDirectory(directoryName)) {
updateHelper.recordFolder(aFile);
recurseCheckUpdatedFiles(updateHelper, aFile);
}
} else {
if (!SolutionReposUtil.ignoreFile(aFile.getName())) {
updateHelper.recordFile(aFile);
}
}
} // End For
}
/**
* This runs a Hibernate query to get just paths and modified times from the repository.
*
* @return Map [path => InfoHolder(LastModifiedDate)
* @author mbatchel
*/
private Map getAllRepositoryModDates() {
Session hibSession = HibernateUtil.getSession();
String nameQuery = "com.pentaho.repository.dbbased.solution.RepositoryFile.filesWithModDates"; //$NON-NLS-1$
Query qry = hibSession.getNamedQuery(nameQuery).setCacheable(true);
List rtn = qry.list();
HashMap modMap = new HashMap();
for (int i = 0; i < rtn.size(); i++) {
Object[] aResult = (Object[]) rtn.get(i);
modMap.put(aResult[0], new InfoHolder(aResult[1], aResult[2]));
}
return modMap;
}
private RepositoryFile findRootRepositoryByName(String rootRepositoryName) {
Session hibSession = HibernateUtil.getSession();
String nameQuery = "com.pentaho.repository.dbbased.solution.RepositoryFile.findNamedRootSolutionFolders"; //$NON-NLS-1$
Query qry = hibSession.getNamedQuery(nameQuery).setCacheable(true);
qry.setString("fileName", rootRepositoryName); //$NON-NLS-1$
RepositoryFile rtn = (RepositoryFile) qry.uniqueResult();
return rtn;
}
public ISolutionFile getRootFolder() {
synchronized (lock) {
if (repositoryName != null) {
rootDirectory = findRootRepositoryByName(getRepositoryName());
if (null == rootDirectory) {
warn(Messages.getString("SolutionRepository.WARN_0003_REPOSITORY_NOT_FOUND_BY_NAME", getRepositoryName())); //$NON-NLS-1$
}
} else {
Session hibSession = HibernateUtil.getSession();
String nameQuery = "com.pentaho.repository.dbbased.solution.RepositoryFile.findAllRootSolutionFolders"; //$NON-NLS-1$
Query qry = hibSession.getNamedQuery(nameQuery).setCacheable(true);
RepositoryFile rtn = (RepositoryFile) qry.uniqueResult();
if (rtn == null) {
return null;
}
repositoryName = rtn.getFullPath() + RepositoryFile.SEPARATOR;
rootDirectory = rtn;
}
}
return rootDirectory;
}
public RepositoryFile getSolutionById(String anId) {
Session hibSession = HibernateUtil.getSession();
RepositoryFile rtn = (RepositoryFile) hibSession.load(RepositoryFile.class, anId);
return rtn;
}
public List getChildrenFilesByParentId(String parentId) {
Session hibSession = HibernateUtil.getSession();
String parentIdQuery = "com.pentaho.repository.dbbased.solution.RepositoryFile.findChildrenFilesByParentId"; //$NON-NLS-1$
Query qry = hibSession.getNamedQuery(parentIdQuery).setString("parentId", parentId).setCacheable(true); //$NON-NLS-1$
return qry.list();
}
/**
* Check <param>systemPath</param> to see if it has the repository name,
* followed by "system", followed by anything else. If it matches,
* remove the repository name from the front of the path, and return the
* path. If not, simply return <param>systemPath</param>
*
* @param systemPath String containing a path.
* @return String <param>systemPath</param> with the repository name removed
* from the path
*/
private String removeRepositoryNameFromSystemPath(String systemPath) {
if (systemPath != null) {
Pattern p = Pattern.compile("[/\\\\]" + getRepositoryName() + "([/\\\\]system[/\\\\].*)"); //$NON-NLS-1$//$NON-NLS-2$
Matcher m = p.matcher(systemPath);
if (m.matches()) {
systemPath = m.group(1);
}
}
return systemPath;
}
public ISolutionFile getFileByPath(String path) {
path = removeRepositoryNameFromSystemPath(path);
if (path == null) {
return getRootFolder();
} else if (SolutionRepositoryBase.isSystemPath(path)) {
return super.getFileByPath(path);
} else {
String fullPath = path.replace('\\', RepositoryFile.SEPARATOR); // use our file seperator
if ((repositoryName != null) && !fullPath.startsWith(repositoryName)) {
if (fullPath.startsWith("/") || fullPath.startsWith("\\")) { //$NON-NLS-1$ //$NON-NLS-2$
fullPath = repositoryName + fullPath.substring(1); // Strip off leading slash
} else {
fullPath = repositoryName + fullPath;
}
}
// TODO sbarkdull, this line should probably be removed, we shouldnt be cleaning up the path for the caller, the caller should be passing us a correct path string
fullPath = fullPath.replaceAll("//", "/"); //$NON-NLS-1$ //$NON-NLS-2$ // Make sure no double-slashes exist
if (fullPath.endsWith("/")) { //$NON-NLS-1$
fullPath = fullPath.substring(0, fullPath.length() - 1);
}
Session hibernateSession = HibernateUtil.getSession();
String nameQuery = "com.pentaho.repository.dbbased.solution.RepositoryFile.findFileByPath"; //$NON-NLS-1$
Query qry = hibernateSession.getNamedQuery(nameQuery).setCacheable(true).setString("fullPath", fullPath); //$NON-NLS-1$
if (qry.list().size() > 0) {
return (RepositoryFile) qry.uniqueResult();
} else {
return super.getFileByPath(path);
}
}
}
public ClassLoader getClassLoader(String path) {
return new DbRepositoryClassLoader(path, this);
}
// --------------------------------------------------------------------
public boolean resourceExists(String solutionPath) {
return getFileByPath(solutionPath) != null;
}
public long resourceSize(String solutionPath) {
RepositoryFile file = (RepositoryFile) getFileByPath(solutionPath);
if (file == null) {
return 0;
}
return file.getData().length;
}
public boolean removeSolutionFile(String solutionPath) {
// Build the path
String fullPath = repositoryName;
String sepStr = Character.toString(RepositoryFile.SEPARATOR);
if ((solutionPath != null) && (solutionPath.length() > 0)) {
if (fullPath.endsWith(sepStr) && solutionPath.startsWith(sepStr)) {
fullPath += solutionPath.substring(1);
} else if (!fullPath.endsWith(sepStr) && !solutionPath.startsWith(sepStr)) {
fullPath += sepStr + solutionPath.substring(1);
} else {
fullPath += solutionPath;
}
} else {
if (fullPath.endsWith(sepStr)) {
fullPath = fullPath.substring(0, fullPath.length() - 1); // take off the path separator character
}
}
RepositoryFile file = (RepositoryFile) getFileByPath(fullPath);
if (file == null) {
return false;
}
if (!hasAccess(file, ACTION_DELETE) && !isPentahoAdministrator()) {
return false;
}
// remove file based files
super.removeSolutionFile(solutionPath);
RepositoryFile parent = (RepositoryFile) file.retrieveParent();
if (parent != null) { // this take care of the case of deleting the
// repository completely
parent.removeChildFile(file);
}
Session hibSession = HibernateUtil.getSession();
Transaction trans = hibSession.beginTransaction();
hibSession.delete(file);
trans.commit();
resetRepository();
return true;
}
public boolean removeSolutionFile(String solution, String path, String fileName) {
String solutionPath = ""; //$NON-NLS-1$
if (solution != null && solution.length() > 0) {
solutionPath += solution;
}
if (path != null && path.length() > 0) {
solutionPath += RepositoryFile.SEPARATOR + path;
}
if (fileName != null && fileName.length() > 0) {
solutionPath += RepositoryFile.SEPARATOR + fileName;
}
return removeSolutionFile(solutionPath);
}
public boolean deleteRepository(String repositoryNameToDelete) {
String oldName = getRepositoryName();
setRepositoryName(repositoryNameToDelete);
boolean result = removeSolutionFile("", "", ""); //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$
setRepositoryName(oldName);
return result;
}
/**
* @return Returns the repositoryName.
*/
public String getRepositoryName() {
return repositoryName == null ? repositoryName : repositoryName.substring(1, repositoryName.length() - 1);
}
/**
* @param repositoryName
* The repositoryName to set.
*/
public void setRepositoryName(String value) {
if (value == null) {
repositoryName = null;
return;
}
String repoName = value;
String pathSep = new StringBuffer().append(RepositoryFile.SEPARATOR).toString();
if (!repoName.startsWith(pathSep)) {
repoName = pathSep + repoName;
}
if (!repoName.endsWith(pathSep)) {
repoName += pathSep;
}
this.repositoryName = repositoryName != null ? repositoryName : repoName;
}
public boolean keepFile(ISolutionFile solutionFile, int actionOperation) {
if (solutionFile instanceof IAclHolder) {
return hasAccess((RepositoryFile) solutionFile, actionOperation);
} else {
return true;
}
}
public void contributeAttributes(ISolutionFile solutionFile, Element childNode) {
if (solutionFile instanceof IAclHolder) {
IPentahoSession sess = getSession();
IAclVoter voter = PentahoSystem.getAclVoter(sess);
PentahoAclEntry access = voter.getEffectiveAcl(sess, (IAclHolder) solutionFile);
if (access != null) {
setXMLPermissionAttributes(access, childNode);
}
}
}
/**
* Add security related attributes to <param>node</param>. The attributes are:
* aclAdministration
* aclExecute
* aclSubscribe
* aclModifyAcl
* Their values will be "true" or "false", depending on the corresponding property
* in the <param>entry</param> parameter.
*
* @param entry PentahoAclEntry
* @param node Element
*/
private void setXMLPermissionAttributes(PentahoAclEntry entry, Element node) {
node.addAttribute("aclAdministration", //$NON-NLS-1$
Boolean.toString(entry.isPermitted(PentahoAclEntry.PERM_ADMINISTRATION)));
node.addAttribute("aclExecute", //$NON-NLS-1$
Boolean.toString(entry.isPermitted(PentahoAclEntry.PERM_EXECUTE)));
node.addAttribute("aclSubscribe", //$NON-NLS-1$
Boolean.toString(entry.isPermitted(PentahoAclEntry.PERM_SUBSCRIBE)));
node.addAttribute("aclModifyAcl", //$NON-NLS-1$
Boolean.toString(entry.isPermitted(PentahoAclEntry.PERM_UPDATE_PERMS)
|| SecurityUtils.isPentahoAdministrator( getSession() ) ));
}
public void exitPoint() {
try {
HibernateUtil.commitTransaction();
HibernateUtil.flushSession();
} catch (Throwable t) {
t.printStackTrace();
}
try {
HibernateUtil.closeSession();
} catch (Throwable t) {
t.printStackTrace();
}
}
public int addSolutionFile(String baseUrl, String path, String fileName, byte[] data, boolean overwrite) {
// TODO mlowery Allow this method for Pentaho administrators only. Use a RunAsManager when calling this method
// from within this class. That way you prevent external callers from directly calling this method.
// baseUrl is ignored
// We handle publish to the system folder differently since it's not in the DB.
if ((path != null) && (path.endsWith("/") || path.endsWith("\\"))) { //$NON-NLS-1$ //$NON-NLS-2$
path = path.substring(0, path.length() - 1);
}
if (SolutionRepositoryBase.isSystemPath(path) && isPentahoAdministrator()) {
// add file using file based technique to send it to disk
return super.addSolutionFile(baseUrl, path, fileName, data, overwrite);
}
RepositoryFile parent = (RepositoryFile) getFileByPath(path);
RepositoryFile reposFile = (RepositoryFile) getFileByPath(path + RepositoryFile.SEPARATOR + fileName);
HibernateUtil.beginTransaction();
if (reposFile == null) {
if (parent == null || !parent.isDirectory() || (!hasAccess(parent, ACTION_CREATE) && !isPentahoAdministrator())) {
HibernateUtil.commitTransaction();
HibernateUtil.flushSession();
return ISolutionRepository.FILE_ADD_FAILED;
}
try {
reposFile = new RepositoryFile(fileName, parent, data);
HibernateUtil.commitTransaction();
HibernateUtil.flushSession();
resetRepository();
super.addSolutionFile(baseUrl, path, fileName, data, overwrite);
return ISolutionRepository.FILE_ADD_SUCCESSFUL;
} catch (Exception e) {
logger.error(e);
return ISolutionRepository.FILE_ADD_FAILED;
}
}
if (!overwrite) {
HibernateUtil.commitTransaction();
HibernateUtil.flushSession();
return ISolutionRepository.FILE_EXISTS;
}
if (hasAccess(reposFile, ACTION_UPDATE) || isPentahoAdministrator()) {
reposFile.setData(data);
super.addSolutionFile(baseUrl, path, fileName, data, overwrite);
resetRepository();
} else {
HibernateUtil.commitTransaction();
HibernateUtil.flushSession();
return ISolutionRepository.FILE_ADD_FAILED;
}
try {
HibernateUtil.commitTransaction();
HibernateUtil.flushSession();
return ISolutionRepository.FILE_ADD_SUCCESSFUL;
} catch (Exception e) {
logger.error(e);
return ISolutionRepository.FILE_ADD_FAILED;
}
}
public int addSolutionFile(String baseUrl, String path, String fileName, File f, boolean overwrite) {
// TODO mlowery Allow this method for Pentaho administrators only. Use a RunAsManager when calling this method
// from within this class. That way you prevent external callers from directly calling this method.
// baseUrl is ignored
byte[] bytes;
try {
bytes = FileHelper.getBytesFromFile(f);
} catch (IOException e) {
error( Messages.getErrorString( "SolutionRepository.ERROR_0014_COULD_NOT_SAVE_FILE", fileName), e ); //$NON-NLS-1$
return ISolutionRepository.FILE_ADD_FAILED;
}
return addSolutionFile(baseUrl, path, fileName, bytes, overwrite);
}
public String[] getAllActionSequences() {
Session hibSession = HibernateUtil.getSession();
String nameQuery = "com.pentaho.repository.dbbased.solution.RepositoryFile.findAllActionSequences"; //$NON-NLS-1$
Query qry = hibSession.getNamedQuery(nameQuery).setCacheable(true);
List rtn = qry.list();
String[] value = new String[rtn.size()];
Iterator iter = rtn.iterator();
int i = 0;
while (iter.hasNext()) {
RepositoryFile file = (RepositoryFile) iter.next();
String path = file.getFullPath();
path = path.substring(repositoryName.length());
value[i++] = path;
}
return value;
}
public long getSolutionFileLastModified(String path) {
RepositoryFile file = (RepositoryFile) getFileByPath(path);
long mod = -1;
if (file != null) {
mod = file.getLastModified();
}
return mod;
}
public boolean supportsAccessControls() {
return true;
}
/**
* TODO mlowery This mapping needs to go away. An AclEntry type should exist per application. AclEntry types should
* not be re-used over more than one app! In other words, get rid of the mapping!
*
* This mapping is currently hard-coded in ISolutionRepository constant initialization.
*/
protected IPermissionMask mapOperationToPermissionMask(int actionOperation) {
int aclMask = actionOperation;
// switch (actionOperation) {
//
// case ISolutionRepository.ACTION_EXECUTE: {
// aclMask = PentahoAclEntry.PERM_EXECUTE;
// break;
// }
// case ISolutionRepository.ACTION_ADMIN: {
// aclMask = PentahoAclEntry.PERM_ADMINISTRATION;
// break;
// }
// case ISolutionRepository.ACTION_SUBSCRIBE: {
// aclMask = PentahoAclEntry.PERM_SUBSCRIBE;
// break;
// }
// case ISolutionRepository.ACTION_CREATE: {
// aclMask = PentahoAclEntry.PERM_CREATE;
// break;
// }
// case ISolutionRepository.ACTION_UPDATE: {
// aclMask = PentahoAclEntry.PERM_UPDATE;
// break;
// }
// case ISolutionRepository.ACTION_DELETE: {
// aclMask = PentahoAclEntry.PERM_DELETE;
// break;
// }
// case ISolutionRepository.ACTION_SHARE: {
// aclMask = PentahoAclEntry.PERM_UPDATE_PERMS;
// break;
// }
// default: {
// // give no permission if incoming actionOperation is unknown
// aclMask = PentahoAclEntry.PERM_NOTHING;
// break;
// }
// }
return new SimplePermissionMask(aclMask);
}
public int publish(String baseUrl, String path, String fileName, byte[] data, boolean overwrite) throws PentahoAccessControlException {
// TODO mlowery This should be wrapped in a transaction to ensure both steps (add file and set perm on file) happen
// together.
// TODO mlowery delegate to other publish version or vice versa
String fullPath = path + RepositoryFile.SEPARATOR + fileName;
boolean alreadyExists = resourceExists(fullPath);
int res = addSolutionFile(baseUrl, path, fileName, data, overwrite);
if (res == ISolutionRepository.FILE_ADD_SUCCESSFUL && !alreadyExists) {
// get the file
ISolutionFile justPublishedFile = getFileByPath(fullPath);
// entire ACL is replaced for new files
AcegiPermissionMgr permissionMgr = AcegiPermissionMgr.instance();
permissionMgr.setPermissions( getDefaultPublishAcl(), justPublishedFile );
}
return res;
}
/**
* Returns the ACL to set on newly published content.
* @return an ACL
*/
protected Map<IPermissionRecipient, IPermissionMask> getDefaultPublishAcl() {
Map<IPermissionRecipient, IPermissionMask> acl = new HashMap<IPermissionRecipient, IPermissionMask>();
// the publisher gets full control
acl.put(new SimpleSession(getSession()), new SimplePermissionMask(PentahoAclEntry.PERM_FULL_CONTROL));
IPentahoSession sess = getSession();
IAclVoter voter = PentahoSystem.getAclVoter(sess);
// and the Pentaho administrator gets full control
acl.put(new SimpleRole(voter.getAdminRole().getAuthority()), new SimplePermissionMask(PentahoAclEntry.PERM_FULL_CONTROL));
return acl;
}
public int publish(String baseUrl, String path, String fileName, File f, boolean overwrite) throws PentahoAccessControlException {
byte[] bytes;
try {
bytes = FileHelper.getBytesFromFile(f);
} catch (IOException e) {
error( Messages.getErrorString( "SolutionRepository.ERROR_0014_COULD_NOT_SAVE_FILE", fileName), e ); //$NON-NLS-1$
return ISolutionRepository.FILE_ADD_FAILED;
}
return publish( baseUrl, path, fileName, bytes, overwrite );
}
public void share(ISolutionFile file, List<IPermissionRecipient> shareRecipients) {
// TODO mlowery Fetch the ACE belonging to this IPermissionRecipient (if any).
AcegiPermissionMgr permissionMgr = AcegiPermissionMgr.instance();
for (IPermissionRecipient shareRecipient : shareRecipients) {
addPermission(file, shareRecipient, new SimplePermissionMask(PentahoAclEntry.PERM_EXECUTE_SUBSCRIBE));
}
}
public void unshare(ISolutionFile file, List<IPermissionRecipient> shareRecipients) {
final int NOT_SHARE = PentahoAclEntry.PERM_EXECUTE_SUBSCRIBE ^ 0xffffffff;
AcegiPermissionMgr permissionMgr = AcegiPermissionMgr.instance();
// make a copy of the ACL in case it is immutable
Map<IPermissionRecipient, IPermissionMask> acl = new HashMap<IPermissionRecipient, IPermissionMask>(permissionMgr.getPermissions(file));
for (IPermissionRecipient shareRecipient : shareRecipients) {
IPermissionMask perm = acl.get(shareRecipient);
if (null != perm) {
acl.put(shareRecipient, new SimplePermissionMask(perm.getMask() & NOT_SHARE));
} else {
// ignore when clients ask to unshare recipients who were not being shared with
}
}
permissionMgr.setPermissions(acl, file);
}
/**
* TODO mlowery Need to throw exception if unauthorized.
*/
public void addPermission(ISolutionFile file, IPermissionRecipient recipient, IPermissionMask permission) {
AcegiPermissionMgr permissionMgr = AcegiPermissionMgr.instance();
if (isPentahoAdministrator() || permissionMgr.hasPermission(new SimpleSession(getSession()), new SimplePermissionMask(
PentahoAclEntry.PERM_UPDATE_PERMS), file)) {
permissionMgr.setPermission(recipient, permission, file);
} else {
warn("request to add permission on file \"" + file.getFileName() + "\" denied");
}
}
/**
* TODO mlowery Need to throw exception if unauthorized.
*/
public void setPermissions(ISolutionFile file, Map<IPermissionRecipient, IPermissionMask> acl) throws PentahoAccessControlException {
AcegiPermissionMgr permissionMgr = AcegiPermissionMgr.instance();
if (isPentahoAdministrator() || permissionMgr.hasPermission(new SimpleSession(getSession()), new SimplePermissionMask(
PentahoAclEntry.PERM_UPDATE_PERMS), file)) {
permissionMgr.setPermissions(acl, file);
} else {
String msg = Messages.getErrorString("SolutionRepository.ERROR_0015_SET_PERMISSIONS_DENIED", file.getFileName() ); //$NON-NLS-1$
warn( msg );
throw new PentahoAccessControlException( msg );
}
}
/**
* TODO mlowery Need to throw exception if unauthorized.
* TODO mlowery If we had a READ_PERMS bit, then it would be enforced here.
*/
public Map<IPermissionRecipient, IPermissionMask> getPermissions(ISolutionFile file) {
AcegiPermissionMgr permissionMgr = AcegiPermissionMgr.instance();
// if (permissionMgr.hasPermission(new SimpleSession(getSession()), new SimplePermissionMask(
// PentahoAclEntry.MANAGE_PERMS), file)) {
// TODO mlowery Need to do a reverse map to get ISolutionRepository permission constants.
return permissionMgr.getPermissions(file);
// } else {
// warn("request to read permissions on file \"" + file.getFileName() + "\" denied");
// return Collections.emptyMap();
// }
}
public ISolutionFile createFolder(File newFolder) throws IOException {
HibernateUtil.beginTransaction();
try {
String solutionRoot = PentahoSystem.getApplicationContext().getSolutionPath("");
File solutionFile = new File(solutionRoot);
if (solutionFile.isDirectory()) {
Map reposFileStructure = this.getAllRepositoryModDates();
/*
* The fromBase and toBase are, for example: From Base: D:\japps\pentaho\my-solutions\solutions To Base: /solutions
*/
String fromBase = solutionFile.getCanonicalPath();
String toBase = (solutionFile.getName().charAt(0) == '/') ? solutionFile.getName() : "/" + solutionFile.getName(); //$NON-NLS-1$
RepositoryUpdateHelper updateHelper = new RepositoryUpdateHelper(fromBase, toBase, reposFileStructure, this);
ISolutionFile returnFile = updateHelper.createFolder(newFolder);
super.createFolder(newFolder);
return returnFile;
}
} finally {
HibernateUtil.commitTransaction();
HibernateUtil.flushSession();
}
return null;
}
}
/***************************************************************************************************************************************************************
* Old Update DB Repository Classes and Methods *************************** // // This method is no longer used - it's here for reference // public List
* oldloadSolutionFromFileSystem(IPentahoSession pSession, String solutionRoot, boolean deleteOrphans) {
* logger.info(Messages.getString("SolutionRepository.INFO_0001_BEGIN_LOAD_DB_REPOSITORY")); //$NON-NLS-1$ // long startTime = System.currentTimeMillis(); File
* solutionFile = new File(solutionRoot); List touched = new ArrayList(); RepositoryFile solution = null; List notTouched = null; if
* (solutionFile.isDirectory()) { String solutionName = solutionFile.getName(); solution = findRootRepositoryByName(solutionName); if (solution == null) {
* solution = new RepositoryFile(solutionName, null, null, solutionFile.lastModified()); } else if (solutionFile.lastModified() != solution.lastModified) {
* solution.setLastModified(solutionFile.lastModified()); logger.info(Messages.getString("SolutionRepository.INFO_0002_UPDATED_FOLDER",
* solution.getFullPath())); //$NON-NLS-1$ } touched.add(solution); oldProcessFileSystem(solutionFile, solution, touched); IAclPublisher aclPublisher =
* PentahoSystem.getAclPublisher(pSession); if (aclPublisher != null) { aclPublisher.publishDefaultAcls(solution); } HibernateUtil.beginTransaction();
* HibernateUtil.makePersistent(solution); notTouched = findNotTouched(touched, solution); if (deleteOrphans) { deleteFilesFromSolutionTree(notTouched); }
* HibernateUtil.commitTransaction(); } else { // TODO throw some sort of exception here } getRootSolutionFolder(); // This ensures that the repository name
* gets set correctly. resetRepository(); logger.info(Messages.getString("SolutionRepository.INFO_0003_END_LOAD_DB_REPOSITORY")); //$NON-NLS-1$ // long endTime =
* System.currentTimeMillis(); // System.out.println("*********** Old Repository Load Time: " + (endTime - startTime) ); return notTouched; } private List
* oldProcessFileSystem(File solutionFile, RepositoryFile parent, List touched) { // recurse the directories File[] files = solutionFile.listFiles(); for (int i =
* 0; i < files.length; i++) { File aFile = files[i]; if (aFile.isDirectory()) { String directoryName = aFile.getName(); if
* (!SolutionReposUtil.ignoreDirectory(directoryName)) { RepositoryFile folder = getFileByPath(parent.getFullPath() + RepositoryFile.PATH_SEPERATOR +
* directoryName); if (folder == null) { folder = new RepositoryFile(directoryName, parent, null, aFile.lastModified());
* logger.info(Messages.getString("SolutionRepository.INFO_0004_ADDED_FOLDER", folder.getFullPath())); //$NON-NLS-1$ } else if (aFile.lastModified() !=
* folder.lastModified) { folder.setParent(parent); folder.setFileName(directoryName); folder.setLastModified(aFile.lastModified());
* logger.info(Messages.getString("SolutionRepository.INFO_0005_UPDATED_FOLDER", folder.getFullPath())); //$NON-NLS-1$ } touched.add(folder);
* oldProcessFileSystem(aFile, folder, touched); } } else { // Process other files if (!SolutionReposUtil.ignoreFile(aFile.getName())) { try { RepositoryFile
* reposFile = getFileByPath(parent.getFullPath() + RepositoryFile.PATH_SEPERATOR + aFile.getName()); byte[] data = getBytesFromFile(aFile); if (reposFile ==
* null) { reposFile = new RepositoryFile(aFile.getName(), parent, data, aFile.lastModified());
* logger.info(Messages.getString("SolutionRepository.INFO_0006_ADDED_FILE", reposFile.getFullPath())); //$NON-NLS-1$ } else if (aFile.lastModified() !=
* reposFile.lastModified) { reposFile.setFileName(aFile.getName()); reposFile.setParent(parent); reposFile.setData(data);
* reposFile.setLastModified(aFile.lastModified()); logger.info(Messages.getString("SolutionRepository.INFO_0007_UPDATED_FILE", reposFile.getFullPath()));
* //$NON-NLS-1$ } touched.add(reposFile); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } return touched; } private
* List findNotTouched(List touched, RepositoryFile solution) { List currentFiles = new ArrayList(); currentFiles = getAllFilesAsList(solution, currentFiles);
* Iterator iter = touched.iterator(); while (iter.hasNext()) { currentFiles.remove(iter.next()); } return currentFiles; } private List
* getAllFilesAsList(RepositoryFile file, List currentFiles) { currentFiles.add(file); if (file.isDirectory()) { Iterator iter =
* file.getChildrenFiles().iterator(); while (iter.hasNext()) { currentFiles = getAllFilesAsList((RepositoryFile) iter.next(), currentFiles); } } return
* currentFiles; } private void deleteFilesFromSolutionTree(List deleteList) { if (deleteList != null) { Iterator iter = deleteList.iterator(); while
* (iter.hasNext()) { RepositoryFile file = (RepositoryFile) iter.next(); RepositoryFile parent = file.getParent(); if (parent != null) { // this take care of
* the case of deleting the // repository completely parent.removeChildFile(file); } } } } End Old Update DB Repository Classes and Methods
* ***************************
**************************************************************************************************************************************************************/
The table below shows all metrics for SolutionRepository.java.




