0001: /*
0002: * Copyright 2005 Pentaho Corporation. All rights reserved.
0003: * This software was developed by Pentaho Corporation and is provided under the terms
0004: * of the Mozilla Public License, Version 1.1, or any later version. You may not use
0005: * this file except in compliance with the license. If you need a copy of the license,
0006: * please go to http://www.mozilla.org/MPL/MPL-1.1.txt. The Original Code is the Pentaho
0007: * BI Platform. The Initial Developer is Pentaho Corporation.
0008: *
0009: * Software distributed under the Mozilla Public License is distributed on an "AS IS"
0010: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. Please refer to
0011: * the license for the specific language governing your rights and limitations.
0012: *
0013: * @created Jun 21, 2005
0014: * @author James Dixon
0015: *
0016: */
0017: package com.pentaho.repository.dbbased.solution;
0018:
0019: import java.io.File;
0020: import java.io.FileNotFoundException;
0021: import java.io.FileOutputStream;
0022: import java.io.IOException;
0023: import java.util.HashMap;
0024: import java.util.Iterator;
0025: import java.util.List;
0026: import java.util.Map;
0027: import java.util.StringTokenizer;
0028: import java.util.regex.Matcher;
0029: import java.util.regex.Pattern;
0030:
0031: import org.dom4j.Document;
0032: import org.dom4j.DocumentHelper;
0033: import org.dom4j.Element;
0034: import org.dom4j.Node;
0035: import org.hibernate.HibernateException;
0036: import org.hibernate.Query;
0037: import org.hibernate.Session;
0038: import org.hibernate.Transaction;
0039: import org.pentaho.core.repository.ISolutionRepository;
0040: import org.pentaho.core.repository.RepositoryException;
0041: import org.pentaho.core.repository.SolutionRepositoryBase;
0042: import org.pentaho.core.session.IPentahoSession;
0043: import org.pentaho.core.solution.IActionSequence;
0044: import org.pentaho.core.solution.ISolutionFile;
0045: import org.pentaho.core.solution.SequenceDefinition;
0046: import org.pentaho.core.solution.SolutionReposUtil;
0047: import org.pentaho.core.solution.SolutionReposUtil.ISolutionFilter;
0048: import org.pentaho.core.system.IPentahoInitializer;
0049: import org.pentaho.core.system.PentahoSystem;
0050: import org.pentaho.core.util.XmlHelper;
0051: import org.pentaho.messages.Messages;
0052: import org.pentaho.repository.HibernateUtil;
0053: import org.pentaho.repository.filebased.solution.FileInfo;
0054: import org.pentaho.util.FileHelper;
0055:
0056: import com.pentaho.repository.subscribe.ISubscriptionRepository;
0057: import com.pentaho.security.SecurityUtils;
0058: import com.pentaho.security.acls.IAclHolder;
0059: import com.pentaho.security.acls.IAclPublisher;
0060: import com.pentaho.security.acls.PentahoAclEntry;
0061: import com.pentaho.security.acls.voter.IAclVoter;
0062:
0063: /**
0064: * @author William Seyler TODO To change the template for this generated type comment go to Window - Preferences - Java -
0065: * Code Style - Code Templates
0066: */
0067: public class SolutionRepository extends SolutionRepositoryBase
0068: implements SolutionReposUtil.ISolutionFilter,
0069: SolutionReposUtil.ISolutionAttributeContributor,
0070: IPentahoInitializer {
0071: private static final long serialVersionUID = -8270135463210017284L;
0072:
0073: private static final String BREAD_CRUMBS_TAG = "breadcrumbs/"; //$NON-NLS-1$
0074:
0075: // private String rootFile;
0076: private String repositoryName;
0077:
0078: private RepositoryFile rootDirectory;
0079:
0080: private byte[] lock = new byte[0];
0081:
0082: private boolean repositoryInit = false;
0083:
0084: public SolutionRepository() {
0085: init();
0086: }
0087:
0088: public void init() {
0089: if (!repositoryInit) {
0090: super .init();
0091: String reposName = PentahoSystem.getSystemSetting(
0092: "solution-repository/db-repository-name", null); //$NON-NLS-1$
0093: if (reposName != null) {
0094: setRepositoryName(reposName);
0095: logger
0096: .info(Messages
0097: .getString(
0098: "SolutionRepository.WARN_0002_USING_SOLUTION_NAME", getRepositoryName())); //$NON-NLS-1$
0099: } else {
0100: logger
0101: .info(Messages
0102: .getString("SolutionRepository.WARN_0001_UNDEFINED_SOLUTION_NAME")); //$NON-NLS-1$
0103: }
0104: RepositoryFile root = (RepositoryFile) getRootFolder();
0105: if (root == null) {
0106: String path = PentahoSystem.getApplicationContext()
0107: .getSolutionPath(""); //$NON-NLS-1$
0108: loadSolutionFromFileSystem(getSession(), path, true);
0109: root = (RepositoryFile) getRootFolder();
0110: }
0111: repositoryInit = true;
0112: }
0113: }
0114:
0115: public IActionSequence getActionSequence(String solutionName,
0116: String actionPath, String sequenceName,
0117: int localLoggingLevel, int actionOperation) {
0118: String action = buildDirectoryPath(solutionName, actionPath,
0119: sequenceName);
0120:
0121: Document actionSequenceDocument = getSolutionDocument(action,
0122: actionOperation);
0123: if (actionSequenceDocument == null) {
0124: return null;
0125: }
0126: IActionSequence actionSequence = SequenceDefinition
0127: .ActionSequenceFactory(actionSequenceDocument,
0128: sequenceName, actionPath, solutionName, this ,
0129: PentahoSystem.getApplicationContext(),
0130: localLoggingLevel);
0131: if (actionSequence == null) {
0132: return null;
0133: }
0134:
0135: return actionSequence;
0136: }
0137:
0138: public boolean hasAccess(RepositoryFile aFile, int actionOperation) {
0139: return SecurityUtils.hasAccess(aFile, actionOperation,
0140: getSession());
0141: }
0142:
0143: public boolean isPentahoAdministrator() {
0144: return SecurityUtils.isPentahoAdministrator(getSession());
0145: }
0146:
0147: public Document getSolutionDocument(String documentPath,
0148: int actionOperation) {
0149: RepositoryFile file = (RepositoryFile) getRepositoryObjectFromCache(documentPath);
0150: if (file == null) { // Not in cache... go to the solution repository
0151: file = (RepositoryFile) getFileByPath(documentPath);
0152: if (file != null) {
0153: putRepositoryObjectInCache(documentPath, file);
0154: } else {
0155: return null; // If it's still null then it doesn't exist
0156: }
0157: }
0158:
0159: if (!hasAccess(file, actionOperation)) {
0160: if (logger.isDebugEnabled()) {
0161: logger
0162: .debug(Messages
0163: .getString(
0164: "SolutionRepository.ACCESS_DENIED", documentPath, Integer.toString(actionOperation))); //$NON-NLS-1$
0165: }
0166: error(Messages
0167: .getString(
0168: "SolutionRepository.ACCESS_DENIED", documentPath, Integer.toString(actionOperation))); //$NON-NLS-1$
0169: return null;
0170: }
0171:
0172: Document document = null;
0173: if (file.getData() != null) {
0174: try {
0175: document = XmlHelper.getDocFromString(new String(file
0176: .getData()));
0177: } catch (Throwable t) {
0178: error(
0179: Messages
0180: .getErrorString(
0181: "SolutionRepository.ERROR_0009_INVALID_DOCUMENT", documentPath), t); //$NON-NLS-1$
0182: return null;
0183: }
0184: } else {
0185: return null;
0186: }
0187: if (document == null && file != null && file.getData() != null) {
0188: // the document exists but cannot be parsed
0189: error(Messages
0190: .getErrorString(
0191: "SolutionRepository.ERROR_0009_INVALID_DOCUMENT", documentPath)); //$NON-NLS-1$
0192: return null;
0193: }
0194: localizeDoc(document, file);
0195: return document;
0196: }
0197:
0198: public void reloadSolutionRepository(IPentahoSession localSession,
0199: int localLoggingLevel) {
0200: this .loggingLevel = localLoggingLevel;
0201: String path = PentahoSystem.getApplicationContext()
0202: .getSolutionPath(""); //$NON-NLS-1$
0203: DbRepositoryClassLoader.clearResourceCache();
0204: loadSolutionFromFileSystem(localSession, path, true);
0205: }
0206:
0207: private void loadSolutionPath(String solutionName, String path,
0208: int localLoggingLevel) {
0209: this .loggingLevel = localLoggingLevel;
0210: if (isCachingAvailable()) {
0211: String localDirStr = buildDirectoryPath(solutionName, path,
0212: null);
0213: Document repository = DocumentHelper.createDocument();
0214: Element rootNode = null;
0215: RepositoryFile directory = (RepositoryFile) getFileByPath(localDirStr);
0216: if (directory.isRoot()) {
0217: rootNode = repository.addElement("repository"); //$NON-NLS-1$
0218: Document indexDoc = getSolutionDocument(directory
0219: .getFullPath()
0220: + RepositoryFile.SEPARATOR
0221: + SolutionRepositoryBase.INDEX_FILENAME,
0222: ISolutionRepository.ACTION_EXECUTE);
0223: if (indexDoc != null) {
0224: addIndexToRepository(indexDoc, directory, rootNode,
0225: path, solutionName);
0226: }
0227: processDir(rootNode, directory, solutionName,
0228: ISolutionRepository.ACTION_EXECUTE,
0229: BROWSE_DEPTH);
0230: } else {
0231: Element filesNode = repository.addElement("files"); //$NON-NLS-1$
0232: rootNode = filesNode.addElement("file"); //$NON-NLS-1$
0233: rootNode
0234: .addAttribute("type", FileInfo.FILE_TYPE_FOLDER); //$NON-NLS-1$
0235: rootNode
0236: .addElement("path").setText(path != null ? path : ""); //$NON-NLS-1$//$NON-NLS-2$
0237: Document indexDoc = getSolutionDocument(directory
0238: .getFullPath()
0239: + RepositoryFile.SEPARATOR
0240: + SolutionRepositoryBase.INDEX_FILENAME,
0241: ISolutionRepository.ACTION_EXECUTE);
0242: if (indexDoc != null) {
0243: addIndexToRepository(indexDoc, directory, rootNode,
0244: path, solutionName);
0245: }
0246: processDir(rootNode, directory, solutionName,
0247: ISolutionRepository.ACTION_EXECUTE,
0248: BROWSE_DEPTH);
0249: filesNode.addElement(LOCATION_ATTR_NAME).setText(
0250: getPathNames(solutionName, path)
0251: + RepositoryFile.SEPARATOR);
0252: }
0253: putRepositoryObjectInCache(localDirStr
0254: + getLocale().toString(), repository);
0255: }
0256: }
0257:
0258: private String buildDirectoryPath(String solution, String path,
0259: String action) {
0260: String localDirStr = repositoryName;
0261: if (solution != null && solution.length() > 0) {
0262: localDirStr += solution;
0263: if (path != null && path.length() > 0) {
0264: localDirStr += RepositoryFile.SEPARATOR;
0265: localDirStr += path;
0266: }
0267: }
0268: if (action != null && action.length() > 0) {
0269: String seperator = new String() + RepositoryFile.SEPARATOR;
0270: if (!localDirStr.endsWith(seperator)) {
0271: localDirStr += RepositoryFile.SEPARATOR;
0272: }
0273: localDirStr += action;
0274: }
0275: return localDirStr;
0276: }
0277:
0278: private Document getCachedSolutionDocument(String solutionName,
0279: String pathName, int actionOperation) {
0280: if (actionOperation == ISolutionRepository.ACTION_EXECUTE) {
0281: String localDirStr = buildDirectoryPath(solutionName,
0282: pathName, null);
0283: Object cachedRepo = this
0284: .getRepositoryObjectFromCache(localDirStr
0285: + getLocale().toString());
0286: if (cachedRepo == null) {
0287: loadSolutionPath(solutionName, pathName,
0288: this .loggingLevel);
0289: cachedRepo = this
0290: .getRepositoryObjectFromCache(localDirStr
0291: + getLocale().toString());
0292: }
0293: return (Document) cachedRepo;
0294: } else {
0295: return null;
0296: }
0297: }
0298:
0299: /*
0300: * private void processDir(Element parentNode, RepositoryFile parentDir, String solutionId, int actionOperation) {
0301: * processDir(parentNode, parentDir, solutionId, actionOperation, true); }
0302: */
0303: private void processDir(Element parentNode,
0304: RepositoryFile parentDir, String solutionId,
0305: int actionOperation, int recurseLevels) {
0306: if (recurseLevels <= 0) {
0307: return;
0308: }
0309: RepositoryFile[] files = parentDir.listRepositoryFiles();
0310: // first process the directories
0311: for (int idx = 0; idx < files.length; idx++) {
0312: if (!files[idx].isDirectory()) {
0313: String fileName = files[idx].getFileName();
0314: if (fileName.equals("Entries") || fileName.equals("Repository") || fileName.equals("Root")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
0315: // ignore any CVS files
0316: continue;
0317: }
0318: if (fileName.toLowerCase().endsWith(".url")) { //$NON-NLS-1$
0319: if (hasAccess(files[idx], actionOperation)) {
0320: addUrlToRepository(files[idx], parentNode);
0321: }
0322: }
0323: if (!fileName.toLowerCase().endsWith(".xaction") && !fileName.toLowerCase().endsWith(".xml")) { //$NON-NLS-1$ //$NON-NLS-2$
0324: // ignore any non-XML files
0325: continue;
0326: }
0327: if (fileName.toLowerCase().equals(
0328: SolutionRepositoryBase.INDEX_FILENAME)) {
0329: // index.xml files are handled in the directory loop below
0330: continue;
0331: }
0332: String path = getSolutionPath(files[idx]);
0333: if (fileName.toLowerCase().endsWith(".xaction")) { //$NON-NLS-1$
0334: // create an action sequence document from this
0335: info(Messages
0336: .getString(
0337: "SolutionRepository.DEBUG_ADDING_ACTION", fileName)); //$NON-NLS-1$
0338: IActionSequence actionSequence = getActionSequence(
0339: solutionId, path, fileName, loggingLevel,
0340: actionOperation);
0341: if (actionSequence == null) {
0342: if ((solutionId == null || solutionId.length() == 0)
0343: && (path == null || path.length() == 0)) {
0344: info(Messages
0345: .getString(
0346: "SolutionRepository.INFO_0008_NOT_ADDED", fileName)); //$NON-NLS-1$
0347: } else {
0348: error(Messages
0349: .getErrorString(
0350: "SolutionRepository.ERROR_0006_INVALID_SEQUENCE_DOCUMENT", fileName)); //$NON-NLS-1$
0351: }
0352: } else {
0353: addToRepository(actionSequence, parentNode,
0354: files[idx]);
0355: }
0356: }
0357: }
0358: }
0359: for (int idx = 0; idx < files.length; idx++) {
0360: if (files[idx].isDirectory()
0361: && (!files[idx].getFileName().equalsIgnoreCase(
0362: "system")) && (!files[idx].getFileName().equalsIgnoreCase("CVS")) && (!files[idx].getFileName().equalsIgnoreCase(".svn"))) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
0363: Element dirNode = parentNode.addElement("file"); //$NON-NLS-1$
0364: dirNode.addAttribute("type", FileInfo.FILE_TYPE_FOLDER); //$NON-NLS-1$
0365: contributeAttributes(files[idx], dirNode);
0366: // TODO read this from the directory index file
0367: String this Solution;
0368: String path = getSolutionPath(files[idx]);
0369: if (solutionId == null) {
0370: this Solution = getSolutionId(files[idx]);
0371: } else {
0372: this Solution = solutionId;
0373: dirNode.addElement("path").setText(path); //$NON-NLS-1$
0374: }
0375: Document indexDoc = getSolutionDocument(files[idx]
0376: .getFullPath()
0377: + RepositoryFile.SEPARATOR
0378: + SolutionRepositoryBase.INDEX_FILENAME,
0379: actionOperation);
0380: if (indexDoc != null) {
0381: addIndexToRepository(indexDoc, files[idx], dirNode,
0382: path, this Solution);
0383: } else {
0384: dirNode.addAttribute("visible", "false"); //$NON-NLS-1$ //$NON-NLS-2$
0385: String dirName = files[idx].getFileName();
0386: dirNode.addAttribute(
0387: "name", XmlHelper.encode(dirName)); //$NON-NLS-1$
0388: dirNode.addElement("title").setText(dirName); //$NON-NLS-1$
0389: }
0390: processDir(dirNode, files[idx], this Solution,
0391: actionOperation, recurseLevels - 1);
0392: }
0393: }
0394: }
0395:
0396: private String getSolutionId(RepositoryFile file) {
0397: String path = file.getFullPath();
0398: if (path.length() < repositoryName.length()) {
0399: return ""; //$NON-NLS-1$
0400: }
0401: path = path.substring(repositoryName.length()); // Strip off the root
0402: // directory
0403: // Strip off the fileName if any
0404: if (path.indexOf(RepositoryFile.SEPARATOR) != -1) {
0405: path = path.substring(0, path
0406: .indexOf(RepositoryFile.SEPARATOR));
0407: }
0408: return path;
0409: }
0410:
0411: private String getSolutionPath(RepositoryFile file) {
0412: String path = file.getFullPath();
0413: try {
0414: path = path.substring(repositoryName.length()); // Strip off the
0415: // root
0416: // directory
0417: // Strip off the filename if there is one
0418: if (!file.isDirectory()) {
0419: path = path.substring(0, path
0420: .lastIndexOf(RepositoryFile.SEPARATOR));
0421: }
0422: // Strip off the solution folder and the following / if any else we
0423: // know we have a solution folder and return empty String
0424: if (path.indexOf(RepositoryFile.SEPARATOR) != -1) {
0425: path = path.substring(path
0426: .indexOf(RepositoryFile.SEPARATOR) + 1);
0427: } else {
0428: return EMPTY_STR;
0429: }
0430: } catch (StringIndexOutOfBoundsException ex) {
0431: return EMPTY_STR;
0432: }
0433: return path;
0434: }
0435:
0436: private void addIndexToRepository(Document indexDoc,
0437: RepositoryFile directoryFile, Element directoryNode,
0438: String path, String solution) {
0439: if (!directoryFile.isDirectory()) {
0440: return;
0441: }
0442: // TODO see if there is a localized attribute file for the current
0443: // locale
0444: String dirName = getValue(
0445: indexDoc,
0446: "/index/name", directoryFile.getFileName().replace('_', ' ')); //$NON-NLS-1$
0447: String description = getValue(indexDoc,
0448: "/index/description", EMPTY_STR); //$NON-NLS-1$
0449: String iconPath = getValue(indexDoc, "/index/icon", EMPTY_STR); //$NON-NLS-1$
0450: String displayType = getValue(indexDoc,
0451: "/index/display-type", "icons"); //$NON-NLS-1$ //$NON-NLS-2$
0452: boolean visible = getValue(indexDoc, "/index/visible", "false").equalsIgnoreCase("true"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
0453:
0454: path = XmlHelper.encode(path);
0455: String name = XmlHelper.encode(directoryFile.getFileName());
0456:
0457: // We want to cache the localized document name if we don't already have it
0458: if (directoryFile.isDirectory()
0459: && getPathNames(solution, path) == null) {
0460: cacheLocalizedDirectoryName(dirName, directoryFile,
0461: solution, path);
0462: }
0463: directoryNode.addAttribute("name", name); //$NON-NLS-1$
0464: directoryNode.addElement("title").setText(dirName); //$NON-NLS-1$
0465:
0466: directoryNode.addAttribute("path", path); //$NON-NLS-1$
0467: directoryNode.addElement("description").setText(description); //$NON-NLS-1$
0468: if (iconPath != null && !iconPath.equals("")) { //$NON-NLS-1$
0469: String rolloverIconPath = null;
0470: int rolloverIndex = iconPath.indexOf("|"); //$NON-NLS-1$
0471: if (rolloverIndex > -1) {
0472: rolloverIconPath = iconPath
0473: .substring(rolloverIndex + 1);
0474: iconPath = iconPath.substring(0, rolloverIndex);
0475: }
0476: if (publishIcon(directoryFile.isDirectory() ? directoryFile
0477: .getFullPath() : directoryFile.retrieveParent()
0478: .getFullPath(), iconPath)) {
0479: directoryNode
0480: .addElement("icon").setText("getImage?image=icons/" + iconPath); //$NON-NLS-1$ //$NON-NLS-2$
0481: } else {
0482: directoryNode.addElement("icon").setText(iconPath); //$NON-NLS-1$
0483: }
0484: if (rolloverIconPath != null) {
0485: if (publishIcon(
0486: directoryFile.isDirectory() ? directoryFile
0487: .getFullPath() : directoryFile
0488: .retrieveParent().getFullPath(),
0489: rolloverIconPath)) {
0490: directoryNode
0491: .addElement("rollovericon").setText("getImage?image=icons/" + rolloverIconPath); //$NON-NLS-1$ //$NON-NLS-2$
0492: } else {
0493: directoryNode
0494: .addElement("rollovericon").setText(rolloverIconPath); //$NON-NLS-1$
0495: }
0496: }
0497: }
0498: Boolean visability = null;
0499: boolean hasAccess = SecurityUtils.hasAccess(directoryFile,
0500: ISolutionRepository.ACTION_EXECUTE, getSession());
0501: if (!hasAccess) {
0502: visability = new Boolean(false);
0503: } else {
0504: visability = new Boolean(visible);
0505: }
0506: directoryNode.addAttribute("visible", visability.toString()); //$NON-NLS-1$
0507: directoryNode.addAttribute("displaytype", displayType); //$NON-NLS-1$
0508: if (solution != null && solution.length() > 0) {
0509: directoryNode.addElement("solution").setText(solution); //$NON-NLS-1$
0510: } else {
0511: directoryNode
0512: .addElement("solution").setText(getSolutionId(directoryFile)); //$NON-NLS-1$
0513: }
0514: }
0515:
0516: private void cacheLocalizedDirectoryName(String localizedPath,
0517: RepositoryFile directoryFile, String solution, String path) {
0518: if (directoryFile.isRoot()) { // We're done and have the final localized string in dirName
0519: putRepositoryObjectInCache(BREAD_CRUMBS_TAG
0520: + buildDirectoryPath(solution, path, null),
0521: localizedPath);
0522: } else { // We've got to process the name of the parent
0523: String localizedAncestors = (String) getRepositoryObjectFromCache(BREAD_CRUMBS_TAG
0524: + directoryFile.retrieveParent().getFullPath());
0525: if (localizedAncestors != null) { // The parents stuff was already cached
0526: localizedPath = localizedAncestors
0527: + RepositoryFile.SEPARATOR + localizedPath;
0528: putRepositoryObjectInCache(BREAD_CRUMBS_TAG
0529: + buildDirectoryPath(solution, path, null),
0530: localizedPath);
0531: } else { // Now we've got to check to see if the parent has an index.xml
0532: Document indexDoc = getSolutionDocument(directoryFile
0533: .retrieveParent().getFullPath()
0534: + RepositoryFile.SEPARATOR
0535: + SolutionRepositoryBase.INDEX_FILENAME,
0536: ISolutionRepository.ACTION_EXECUTE);
0537: if (indexDoc == null) {
0538: localizedPath = directoryFile.retrieveParent()
0539: .getFileName()
0540: + RepositoryFile.SEPARATOR + localizedPath;
0541: } else {
0542: localizedPath = getValue(
0543: indexDoc,
0544: "/index/name", directoryFile.retrieveParent().getFileName().replace('_', ' ')) + RepositoryFile.SEPARATOR + localizedPath; //$NON-NLS-1$
0545: }
0546: cacheLocalizedDirectoryName(
0547: localizedPath,
0548: (RepositoryFile) directoryFile.retrieveParent(),
0549: solution, path);
0550: }
0551: }
0552: }
0553:
0554: private void addUrlToRepository(RepositoryFile file,
0555: Element parentNode) {
0556: String urlContent = new String(file.getData());
0557: StringTokenizer tokenizer = new StringTokenizer(urlContent,
0558: "\n"); //$NON-NLS-1$
0559: String url = null;
0560: String title = file.getFileName();
0561: String description = null;
0562: String iconPath = null;
0563: String target = null;
0564: while (tokenizer.hasMoreTokens()) {
0565: String line = tokenizer.nextToken();
0566: int pos = line.indexOf('=');
0567: if (pos > 0) {
0568: String name = line.substring(0, pos);
0569: String value = line.substring(pos + 1);
0570: if ((value != null) && (value.length() > 0)
0571: && (value.charAt(value.length() - 1) == '\r')) {
0572: value = value.substring(0, value.length() - 1);
0573: }
0574: if ("URL".equalsIgnoreCase(name)) { //$NON-NLS-1$
0575: url = value;
0576: }
0577: if ("name".equalsIgnoreCase(name)) { //$NON-NLS-1$
0578: title = value;
0579: }
0580: if ("description".equalsIgnoreCase(name)) { //$NON-NLS-1$
0581: description = value;
0582: }
0583: if ("icon".equalsIgnoreCase(name)) { //$NON-NLS-1$
0584: iconPath = value;
0585: }
0586: if ("target".equalsIgnoreCase(name)) { //$NON-NLS-1$
0587: target = value;
0588: }
0589: }
0590: }
0591: if (url != null) {
0592: // now create an entry for the database
0593: Element dirNode = parentNode.addElement("file"); //$NON-NLS-1$
0594: dirNode.addAttribute("type", FileInfo.FILE_TYPE_URL); //$NON-NLS-1$
0595: dirNode.addElement("filename").setText(file.getFileName()); //$NON-NLS-1$
0596: dirNode.addElement("title").setText(title); //$NON-NLS-1$
0597: if (target != null) {
0598: dirNode.addElement("target").setText(target); //$NON-NLS-1$
0599: }
0600: if (description != null) {
0601: dirNode.addElement("description").setText(description); //$NON-NLS-1$
0602: }
0603: if (iconPath != null && !iconPath.equals("")) { //$NON-NLS-1$
0604: String rolloverIconPath = null;
0605: int rolloverIndex = iconPath.indexOf("|"); //$NON-NLS-1$
0606: if (rolloverIndex > -1) {
0607: rolloverIconPath = iconPath
0608: .substring(rolloverIndex + 1);
0609: iconPath = iconPath.substring(0, rolloverIndex);
0610: }
0611: if (publishIcon(file.retrieveParent().getFullPath(),
0612: iconPath)) {
0613: dirNode
0614: .addElement("icon").setText("getImage?image=icons/" + iconPath); //$NON-NLS-1$ //$NON-NLS-2$
0615: } else {
0616: dirNode.addElement("icon").setText(iconPath); //$NON-NLS-1$
0617: }
0618: if (rolloverIconPath != null) {
0619: if (publishIcon(
0620: file.retrieveParent().getFullPath(),
0621: rolloverIconPath)) {
0622: dirNode
0623: .addElement("rollovericon").setText("getImage?image=icons/" + rolloverIconPath); //$NON-NLS-1$ //$NON-NLS-2$
0624: } else {
0625: dirNode
0626: .addElement("rollovericon").setText(rolloverIconPath); //$NON-NLS-1$
0627: }
0628: }
0629: }
0630: dirNode.addElement("url").setText(url); //$NON-NLS-1$
0631: dirNode.addAttribute("visible", "true"); //$NON-NLS-1$ //$NON-NLS-2$
0632: dirNode.addAttribute(
0633: "displaytype", FileInfo.FILE_DISPLAY_TYPE_URL); //$NON-NLS-1$
0634: localizeDoc(dirNode, file);
0635: }
0636: }
0637:
0638: private void addToRepository(IActionSequence actionSequence,
0639: Element parentNode, RepositoryFile file) {
0640: Element dirNode = parentNode.addElement("file"); //$NON-NLS-1$
0641: dirNode.addAttribute("type", FileInfo.FILE_TYPE_ACTIVITY); //$NON-NLS-1$
0642: contributeAttributes(file, dirNode);
0643: if (actionSequence.getSequenceName() == null
0644: || actionSequence.getSolutionPath() == null
0645: || actionSequence.getSolutionName() == null) {
0646: error(Messages
0647: .getString("SolutionRepository.ERROR_0008_ACTION_SEQUENCE_NAME_INVALID")); //$NON-NLS-1$
0648: return;
0649: }
0650: dirNode
0651: .addElement("filename").setText(actionSequence.getSequenceName()); //$NON-NLS-1$
0652: dirNode
0653: .addElement("path").setText(actionSequence.getSolutionPath()); //$NON-NLS-1$
0654: dirNode
0655: .addElement("solution").setText(actionSequence.getSolutionName()); //$NON-NLS-1$
0656: String title = actionSequence.getTitle();
0657: if (title == null) {
0658: dirNode
0659: .addElement("title").setText(actionSequence.getSequenceName()); //$NON-NLS-1$
0660: } else {
0661: dirNode.addElement("title").setText(title); //$NON-NLS-1$
0662: }
0663: String description = actionSequence.getDescription();
0664: if (description == null) {
0665: dirNode.addElement("description"); //$NON-NLS-1$
0666: } else {
0667: dirNode.addElement("description").setText(description); //$NON-NLS-1$
0668: }
0669: String author = actionSequence.getAuthor();
0670: if (author == null) {
0671: dirNode.addElement("author"); //$NON-NLS-1$
0672: } else {
0673: dirNode.addElement("author").setText(author); //$NON-NLS-1$
0674: }
0675: String iconPath = actionSequence.getIcon();
0676: if (iconPath != null && !iconPath.equals("")) { //$NON-NLS-1$
0677: String rolloverIconPath = null;
0678: int rolloverIndex = iconPath.indexOf("|"); //$NON-NLS-1$
0679: if (rolloverIndex > -1) {
0680: rolloverIconPath = iconPath
0681: .substring(rolloverIndex + 1);
0682: iconPath = iconPath.substring(0, rolloverIndex);
0683: }
0684: if (publishIcon(file.retrieveParent().getFullPath(),
0685: iconPath)) {
0686: dirNode
0687: .addElement("icon").setText("getImage?image=icons/" + iconPath); //$NON-NLS-1$ //$NON-NLS-2$
0688: } else {
0689: dirNode
0690: .addElement("icon").setText(actionSequence.getIcon()); //$NON-NLS-1$
0691: }
0692: if (rolloverIconPath != null) {
0693: if (publishIcon(file.retrieveParent().getFullPath(),
0694: rolloverIconPath)) {
0695: dirNode
0696: .addElement("rollovericon").setText("getImage?image=icons/" + rolloverIconPath); //$NON-NLS-1$ //$NON-NLS-2$
0697: } else {
0698: dirNode
0699: .addElement("rollovericon").setText(rolloverIconPath); //$NON-NLS-1$
0700: }
0701: }
0702: }
0703: String displayType = actionSequence.getResultType();
0704: if ((displayType == null)
0705: || ("none".equalsIgnoreCase(displayType))) { //$NON-NLS-1$
0706: // this should be hidden from users
0707: dirNode.addAttribute("visible", "false"); //$NON-NLS-1$ //$NON-NLS-2$
0708: } else {
0709: dirNode.addAttribute("visible", "true"); //$NON-NLS-1$ //$NON-NLS-2$
0710: dirNode.addAttribute("displaytype", displayType); //$NON-NLS-1$
0711: }
0712: ISubscriptionRepository subscriptionRepository = PentahoSystem
0713: .getSubscriptionRepository(this .getSession());
0714: boolean subscribable = subscriptionRepository
0715: .getContentByActionReference(actionSequence
0716: .getSolutionName()
0717: + '/'
0718: + actionSequence.getSolutionPath()
0719: + '/'
0720: + actionSequence.getSequenceName()) != null;
0721: dirNode
0722: .addElement("properties").setText("subscribable=" + Boolean.toString(subscribable)); //$NON-NLS-1$ //$NON-NLS-2$
0723: }
0724:
0725: private boolean publishIcon(String dirPath, String iconPath) {
0726: String pathSeperator = new StringBuffer().append(
0727: RepositoryFile.SEPARATOR).toString();
0728: if (!iconPath.startsWith(pathSeperator)) {
0729: iconPath = pathSeperator + iconPath;
0730: }
0731: String iconRepositoryPath = dirPath + iconPath;
0732: RepositoryFile iconSource = (RepositoryFile) getFileByPath(iconRepositoryPath);
0733: if (iconSource != null) {
0734: File tmpDir = getFile("system/tmp/icons", true); //$NON-NLS-1$
0735: tmpDir.mkdirs();
0736: File iconDestintation = new File(tmpDir.getAbsoluteFile()
0737: + File.separator + iconPath);
0738: if (iconDestintation.exists()) {
0739: iconDestintation.delete();
0740: }
0741: try {
0742: FileOutputStream outputStream = new FileOutputStream(
0743: iconDestintation);
0744: outputStream.write(iconSource.getData());
0745: outputStream.flush();
0746: outputStream.close();
0747: } catch (FileNotFoundException e) {
0748: // this one is not very likey
0749: } catch (IOException e) {
0750: }
0751: return true;
0752: } else {
0753: return false;
0754: }
0755: }
0756:
0757: public Document getSolutions(String solutionName, String pathName,
0758: int actionOperation, boolean visibleOnly) {
0759: return getCachedSolutionDocument(solutionName, pathName,
0760: actionOperation);
0761: }
0762:
0763: private String getPathNames(String solution, String path) {
0764: String key = BREAD_CRUMBS_TAG
0765: + buildDirectoryPath(solution, path, null);
0766: return (String) getRepositoryObjectFromCache(key);
0767: }
0768:
0769: // TODO sbarkdull, refactor, this should either be private, or should be in the XmlHelper class (prefer 2nd)
0770: // maybe rename getNodeTextOrDefault
0771: public String getValue(Document doc, String xPath,
0772: String defaultValue) {
0773: if (doc != null) {
0774: Node node = doc.selectSingleNode(xPath);
0775: if (node == null) {
0776: return defaultValue;
0777: }
0778: return node.getText();
0779: }
0780: return defaultValue;
0781: }
0782:
0783: public Document getSolutionTree(int actionOperation) {
0784: return getSolutionTree(actionOperation, this );
0785: }
0786:
0787: public Document getSolutionTree(int actionOperation,
0788: ISolutionFilter filter) {
0789: Document document = DocumentHelper.createDocument();
0790: getRootFolder();
0791: if (!hasAccess(rootDirectory, actionOperation)) {
0792: if (logger.isDebugEnabled()) {
0793: logger
0794: .debug(Messages
0795: .getString(
0796: "SolutionRepository.ACCESS_DENIED", rootDirectory.getFullPath(), Integer.toString(actionOperation))); //$NON-NLS-1$
0797: }
0798: return document; // Empty Document
0799: }
0800: Element root = document.addElement("tree"); //$NON-NLS-1$
0801: SolutionReposUtil.processSolutionTree(root, rootDirectory,
0802: filter, actionOperation);
0803: return document;
0804: }
0805:
0806: public Document getSolutionStructure(int actionOperation) {
0807: Document document = DocumentHelper.createDocument();
0808: getRootFolder();
0809: Element root = document.addElement(ROOT_NODE_NAME)
0810: .addAttribute(LOCATION_ATTR_NAME,
0811: rootDirectory.getFullPath());
0812: SolutionReposUtil.processSolutionStructure(root, rootDirectory,
0813: this , actionOperation);
0814: return document;
0815: }
0816:
0817: public String resetSolutionFromFileSystem(IPentahoSession pSession) {
0818: try {
0819: RepositoryFile solution = (RepositoryFile) getRootFolder();
0820: if (solution != null) {
0821: HibernateUtil.beginTransaction();
0822: HibernateUtil.makeTransient(solution);
0823: HibernateUtil.commitTransaction();
0824: HibernateUtil.flushSession();
0825: }
0826: this .loadSolutionFromFileSystem(pSession, PentahoSystem
0827: .getApplicationContext().getSolutionPath(""), true); //$NON-NLS-1$
0828: } catch (Exception e) {
0829: return Messages
0830: .getString(
0831: "SolutionRepository.ERROR_0013_RESET_FAILED", e.getLocalizedMessage()); //$NON-NLS-1$
0832: }
0833: return Messages
0834: .getString("SolutionRepository.INFO_0009_RESET_SUCCESS"); //$NON-NLS-1$
0835: }
0836:
0837: /** *************************** New Update DB Repository Classes and Methods ******************************* */
0838: /**
0839: * This method loads solution files and folders from the file system into the RDBMS repository.
0840: *
0841: * @param pSession
0842: * Users' Session
0843: * @param solutionRoot
0844: * The file system root folder
0845: * @param deleteOrphans
0846: * Whether to delete stranded references from RDBMS repository
0847: * @return List of orphans that were deleted - returns list of deleted solution files.
0848: * @throws RepositoryException
0849: * @author mbatchel
0850: */
0851: public synchronized List loadSolutionFromFileSystem(
0852: IPentahoSession pSession, String solutionRoot,
0853: boolean deleteOrphans) throws RepositoryException {
0854: logger
0855: .info(Messages
0856: .getString("SolutionRepository.INFO_0001_BEGIN_LOAD_DB_REPOSITORY")); //$NON-NLS-1$
0857: HibernateUtil.beginTransaction();
0858: File solutionFile = new File(solutionRoot);
0859: RepositoryFile solution = null;
0860: try {
0861: if (solutionFile.isDirectory()) {
0862: Map reposFileStructure = this
0863: .getAllRepositoryModDates();
0864: /*
0865: * The fromBase and toBase are, for example: From Base: D:\japps\pentaho\my-solutions\solutions To Base:
0866: * /solutions
0867: */
0868: String fromBase = solutionFile.getCanonicalPath();
0869: String toBase = (solutionFile.getName().charAt(0) == '/') ? solutionFile
0870: .getName()
0871: : "/" + solutionFile.getName(); //$NON-NLS-1$
0872: RepositoryUpdateHelper updateHelper = new RepositoryUpdateHelper(
0873: fromBase, toBase, reposFileStructure, this );
0874: //
0875: // Check to see if we're just doing a refresh...
0876: //
0877: InfoHolder checkBase = (InfoHolder) reposFileStructure
0878: .get(toBase);
0879: if (checkBase != null) {
0880: // It's there - we're refreshing
0881: checkBase.touched = true;
0882: // Get the solution object from Hibernate
0883: solution = (RepositoryFile) getFileByPath(null); // Hibernate Query
0884: updateHelper.createdOrRetrievedFolders.put(toBase,
0885: solution); // Store for later reference
0886: } else {
0887: solution = new RepositoryFile(solutionFile
0888: .getName(), null, null, solutionFile
0889: .lastModified()); // Create
0890: // entry
0891: // Put the created folder into the created map for later use
0892: updateHelper.createdOrRetrievedFolders.put(toBase,
0893: solution); // Store for later reference
0894: logger
0895: .info(Messages
0896: .getString(
0897: "SolutionRepository.INFO_0002_UPDATED_FOLDER", solution.getFullPath())); //$NON-NLS-1$
0898: }
0899: repositoryName = solution.getFullPath()
0900: + RepositoryFile.SEPARATOR;
0901: // Find and record changes and updates
0902: recurseCheckUpdatedFiles(updateHelper, solutionFile);
0903: //
0904: // The following lines are order dependent
0905: //
0906: // Handle updated Files and Folders
0907: updateHelper.processUpdates();
0908: // Handle added folders and files
0909: updateHelper.processAdditions();
0910: // Save solution state
0911: HibernateUtil.makePersistent(solution);
0912: // Process deletions
0913: List deletions = updateHelper
0914: .processDeletions(deleteOrphans);
0915: // Publish ACLs
0916: IAclPublisher aclPublisher = PentahoSystem
0917: .getAclPublisher(pSession);
0918: if (aclPublisher != null) {
0919: aclPublisher.publishDefaultAcls(solution);
0920: }
0921: // Tell Hibernate we're ready for a commit - we're done now
0922: HibernateUtil.commitTransaction();
0923: HibernateUtil.flushSession();
0924: // The next two lines were from the old code
0925: resetRepository(); // Clear the cache of old stuff
0926: logger
0927: .info(Messages
0928: .getString("SolutionRepository.INFO_0003_END_LOAD_DB_REPOSITORY")); //$NON-NLS-1$
0929: return deletions;
0930: } else {
0931: throw new RepositoryException(
0932: Messages
0933: .getString(
0934: "SolutionRepository.ERROR_0012_INVALID_SOLUTION_ROOT", solutionRoot)); //$NON-NLS-1$
0935: }
0936: } catch (HibernateException hibernateException) {
0937: // re-throw exception so that it abandons the process
0938: try {
0939: HibernateUtil.rollbackTransaction();
0940: } catch (HibernateException ignored) {
0941: logger
0942: .error(
0943: "SolutionRepository.ERROR_0011_TRANSACTION_FAILED", ignored); //$NON-NLS-1$
0944: }
0945: throw new RepositoryException(hibernateException);
0946: } catch (IOException ex) {
0947: // re-throw exception so that it abandons the process
0948: throw new RepositoryException(ex);
0949: }
0950: }
0951:
0952: /**
0953: * This method builds up lists of the files modified (based on date/time), new folders, and new files.
0954: *
0955: * @param reposFileStructure
0956: * Map of what's currently in the DB repository
0957: * @param solutionFile
0958: * The folder to begin working through
0959: * @param updatedFiles
0960: * List of files updated
0961: * @param newFolders
0962: * List of new folders
0963: * @param newFiles
0964: * List of new files
0965: * @throws IOException
0966: * @author mbatchel
0967: */
0968: private void recurseCheckUpdatedFiles(
0969: RepositoryUpdateHelper updateHelper, File solutionFile)
0970: throws IOException {
0971: File[] files = solutionFile.listFiles();
0972: for (int i = 0; i < files.length; i++) {
0973: File aFile = files[i];
0974: if (aFile.isDirectory()) {
0975: String directoryName = aFile.getName();
0976: if (!SolutionReposUtil.ignoreDirectory(directoryName)) {
0977: updateHelper.recordFolder(aFile);
0978: recurseCheckUpdatedFiles(updateHelper, aFile);
0979: }
0980: } else {
0981: if (!SolutionReposUtil.ignoreFile(aFile.getName())) {
0982: updateHelper.recordFile(aFile);
0983: }
0984: }
0985: } // End For
0986: }
0987:
0988: /**
0989: * This runs a Hibernate query to get just paths and modified times from the repository.
0990: *
0991: * @return Map [path => InfoHolder(LastModifiedDate)
0992: * @author mbatchel
0993: */
0994: private Map getAllRepositoryModDates() {
0995: Session hibSession = HibernateUtil.getSession();
0996: String nameQuery = "com.pentaho.repository.dbbased.solution.RepositoryFile.filesWithModDates"; //$NON-NLS-1$
0997: Query qry = hibSession.getNamedQuery(nameQuery).setCacheable(
0998: true);
0999: List rtn = qry.list();
1000: HashMap modMap = new HashMap();
1001: for (int i = 0; i < rtn.size(); i++) {
1002: Object[] aResult = (Object[]) rtn.get(i);
1003: modMap.put(aResult[0], new InfoHolder(aResult[1],
1004: aResult[2]));
1005: }
1006: return modMap;
1007: }
1008:
1009: private RepositoryFile findRootRepositoryByName(
1010: String rootRepositoryName) {
1011: Session hibSession = HibernateUtil.getSession();
1012: String nameQuery = "com.pentaho.repository.dbbased.solution.RepositoryFile.findNamedRootSolutionFolders"; //$NON-NLS-1$
1013: Query qry = hibSession.getNamedQuery(nameQuery).setCacheable(
1014: true);
1015: qry.setString("fileName", rootRepositoryName); //$NON-NLS-1$
1016: RepositoryFile rtn = (RepositoryFile) qry.uniqueResult();
1017: return rtn;
1018: }
1019:
1020: public ISolutionFile getRootFolder() {
1021: synchronized (lock) {
1022: if (repositoryName != null) {
1023: rootDirectory = findRootRepositoryByName(getRepositoryName());
1024: } else {
1025: Session hibSession = HibernateUtil.getSession();
1026: String nameQuery = "com.pentaho.repository.dbbased.solution.RepositoryFile.findAllRootSolutionFolders"; //$NON-NLS-1$
1027: Query qry = hibSession.getNamedQuery(nameQuery)
1028: .setCacheable(true);
1029: RepositoryFile rtn = (RepositoryFile) qry
1030: .uniqueResult();
1031: if (rtn == null) {
1032: return null;
1033: }
1034: repositoryName = rtn.getFullPath()
1035: + RepositoryFile.SEPARATOR;
1036: rootDirectory = rtn;
1037: }
1038: }
1039: return rootDirectory;
1040: }
1041:
1042: public RepositoryFile getSolutionById(String anId) {
1043: Session hibSession = HibernateUtil.getSession();
1044: RepositoryFile rtn = (RepositoryFile) hibSession.load(
1045: RepositoryFile.class, anId);
1046: return rtn;
1047: }
1048:
1049: public List getChildrenFilesByParentId(String parentId) {
1050: Session hibSession = HibernateUtil.getSession();
1051: String parentIdQuery = Messages
1052: .getString("SolutionRepository.QUERY_FIND_CHILDREN_BY_PARENT_ID"); //$NON-NLS-1$
1053: Query qry = hibSession.getNamedQuery(parentIdQuery).setString(
1054: "parentId", parentId).setCacheable(true); //$NON-NLS-1$
1055: return qry.list();
1056: }
1057:
1058: /**
1059: * Check <param>systemPath</param> to see if it has the repository name,
1060: * followed by "system", followed by anything else. If it matches,
1061: * remove the repository name from the front of the path, and return the
1062: * path. If not, simply return <param>systemPath</param>
1063: *
1064: * @param systemPath String containing a path.
1065: * @return String <param>systemPath</param> with the repository name removed
1066: * from the path
1067: */
1068: private String removeRepositoryNameFromSystemPath(String systemPath) {
1069: if (systemPath != null) {
1070: Pattern p = Pattern
1071: .compile("[/\\\\]" + getRepositoryName() + "([/\\\\]system[/\\\\].*)"); //$NON-NLS-1$//$NON-NLS-2$
1072: Matcher m = p.matcher(systemPath);
1073: if (m.matches()) {
1074: systemPath = m.group(1);
1075: }
1076: }
1077: return systemPath;
1078: }
1079:
1080: public ISolutionFile getFileByPath(String path) {
1081:
1082: path = removeRepositoryNameFromSystemPath(path);
1083: if (path == null) {
1084: return getRootFolder();
1085: } else if (SolutionRepositoryBase.isSystemPath(path)) {
1086: return super .getFileByPath(path);
1087: } else {
1088: String fullPath = path.replace('\\',
1089: RepositoryFile.SEPARATOR); // use our file seperator
1090: if ((repositoryName != null)
1091: && !fullPath.startsWith(repositoryName)) {
1092: if (fullPath.startsWith("/") || fullPath.startsWith("\\")) { //$NON-NLS-1$ //$NON-NLS-2$
1093: fullPath = repositoryName + fullPath.substring(1); // Strip off leading slash
1094: } else {
1095: fullPath = repositoryName + fullPath;
1096: }
1097: }
1098: // 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
1099: fullPath = fullPath.replaceAll("//", "/"); //$NON-NLS-1$ //$NON-NLS-2$ // Make sure no double-slashes exist
1100: if (fullPath.endsWith("/")) { //$NON-NLS-1$
1101: fullPath = fullPath.substring(0, fullPath.length() - 1);
1102: }
1103: Session hibernateSession = HibernateUtil.getSession();
1104: String nameQuery = Messages
1105: .getString("SolutionRepository.QUERY_FIND_FILE_BY_PATH"); //$NON-NLS-1$
1106: Query qry = hibernateSession.getNamedQuery(nameQuery)
1107: .setCacheable(true).setString("fullPath", fullPath); //$NON-NLS-1$
1108: if (qry.list().size() > 0) {
1109: return (RepositoryFile) qry.uniqueResult();
1110: } else {
1111: return super .getFileByPath(path);
1112: }
1113: }
1114: }
1115:
1116: public ClassLoader getClassLoader(String path) {
1117: return new DbRepositoryClassLoader(path, this );
1118: }
1119:
1120: // --------------------------------------------------------------------
1121: public boolean resourceExists(String solutionPath) {
1122: return getFileByPath(solutionPath) != null;
1123: }
1124:
1125: public long resourceSize(String solutionPath) {
1126: RepositoryFile file = (RepositoryFile) getFileByPath(solutionPath);
1127: if (file == null) {
1128: return 0;
1129: }
1130: return file.getData().length;
1131: }
1132:
1133: public boolean removeSolutionFile(String solutionPath) {
1134: // remove file based files
1135: super .removeSolutionFile(solutionPath);
1136: // Build the path
1137: String fullPath = repositoryName;
1138: String sepStr = Character.toString(RepositoryFile.SEPARATOR);
1139: if ((solutionPath != null) && (solutionPath.length() > 0)) {
1140: if (fullPath.endsWith(sepStr)
1141: && solutionPath.startsWith(sepStr)) {
1142: fullPath += solutionPath.substring(1);
1143: } else if (!fullPath.endsWith(sepStr)
1144: && !solutionPath.startsWith(sepStr)) {
1145: fullPath += sepStr + solutionPath.substring(1);
1146: } else {
1147: fullPath += solutionPath;
1148: }
1149: } else {
1150: if (fullPath.endsWith(sepStr)) {
1151: fullPath = fullPath.substring(0, fullPath.length() - 1); // take off the path separator character
1152: }
1153: }
1154: RepositoryFile file = (RepositoryFile) getFileByPath(fullPath);
1155: if (file == null) {
1156: return false;
1157: }
1158: RepositoryFile parent = (RepositoryFile) file.retrieveParent();
1159: if (parent != null) { // this take care of the case of deleting the
1160: // repository completely
1161: parent.removeChildFile(file);
1162: }
1163: Session hibSession = HibernateUtil.getSession();
1164: Transaction trans = hibSession.beginTransaction();
1165: hibSession.delete(file);
1166: trans.commit();
1167: resetRepository();
1168: return true;
1169: }
1170:
1171: public boolean removeSolutionFile(String solution, String path,
1172: String fileName) {
1173: String solutionPath = ""; //$NON-NLS-1$
1174: if (solution != null && solution.length() > 0) {
1175: solutionPath += solution;
1176: }
1177: if (path != null && path.length() > 0) {
1178: solutionPath += RepositoryFile.SEPARATOR + path;
1179: }
1180: if (fileName != null && fileName.length() > 0) {
1181: solutionPath += RepositoryFile.SEPARATOR + fileName;
1182: }
1183: return removeSolutionFile(solutionPath);
1184: }
1185:
1186: public boolean deleteRepository(String repositoryNameToDelete) {
1187: String oldName = getRepositoryName();
1188: setRepositoryName(repositoryNameToDelete);
1189: boolean result = removeSolutionFile("", "", ""); //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$
1190: setRepositoryName(oldName);
1191: return result;
1192: }
1193:
1194: /**
1195: * @return Returns the repositoryName.
1196: */
1197: public String getRepositoryName() {
1198: return repositoryName == null ? repositoryName : repositoryName
1199: .substring(1, repositoryName.length() - 1);
1200: }
1201:
1202: /**
1203: * @param repositoryName
1204: * The repositoryName to set.
1205: */
1206: public void setRepositoryName(String value) {
1207: if (value == null) {
1208: repositoryName = null;
1209: return;
1210: }
1211: String repoName = value;
1212: String pathSep = new StringBuffer().append(
1213: RepositoryFile.SEPARATOR).toString();
1214: if (!repoName.startsWith(pathSep)) {
1215: repoName = pathSep + repoName;
1216: }
1217: if (!repoName.endsWith(pathSep)) {
1218: repoName += pathSep;
1219: }
1220: this .repositoryName = repositoryName != null ? repositoryName
1221: : repoName;
1222: }
1223:
1224: public boolean keepFile(ISolutionFile solutionFile,
1225: int actionOperation) {
1226: if (solutionFile instanceof IAclHolder) {
1227: return hasAccess((RepositoryFile) solutionFile,
1228: actionOperation);
1229: } else {
1230: return true;
1231: }
1232: }
1233:
1234: public void contributeAttributes(ISolutionFile solutionFile,
1235: Element childNode) {
1236: if (solutionFile instanceof IAclHolder) {
1237: IPentahoSession sess = getSession();
1238: IAclVoter voter = PentahoSystem.getAclVoter(sess);
1239: PentahoAclEntry access = voter.getEffectiveAcl(sess,
1240: (IAclHolder) solutionFile);
1241: if (access != null) {
1242: access.setXMLPermissionAttributes(childNode);
1243: }
1244: }
1245: }
1246:
1247: public void exitPoint() {
1248: try {
1249: HibernateUtil.commitTransaction();
1250: HibernateUtil.flushSession();
1251: } catch (Throwable t) {
1252: t.printStackTrace();
1253: }
1254: try {
1255: HibernateUtil.closeSession();
1256: } catch (Throwable t) {
1257: t.printStackTrace();
1258: }
1259: }
1260:
1261: public int addSolutionFile(String baseUrl, String path,
1262: String fileName, byte[] data, boolean overwrite) {
1263: // baseUrl is ignored
1264: // We handle publish to the system folder differently since it's not in the DB.
1265: if ((path != null)
1266: && (path.endsWith("/") || path.endsWith("\\"))) { //$NON-NLS-1$ //$NON-NLS-2$
1267: path = path.substring(0, path.length() - 1);
1268: }
1269: if (SolutionRepositoryBase.isSystemPath(path)
1270: && isPentahoAdministrator()) {
1271: // add file using file based technique to send it to disk
1272: return super .addSolutionFile(baseUrl, path, fileName, data,
1273: overwrite);
1274: }
1275: RepositoryFile parent = (RepositoryFile) getFileByPath(path);
1276: RepositoryFile reposFile = (RepositoryFile) getFileByPath(path
1277: + RepositoryFile.SEPARATOR + fileName);
1278: HibernateUtil.beginTransaction();
1279: if (reposFile == null) {
1280: if (parent == null
1281: || !parent.isDirectory()
1282: || (!hasAccess(parent, ACTION_CREATE) && !isPentahoAdministrator())) {
1283: HibernateUtil.commitTransaction();
1284: HibernateUtil.flushSession();
1285: return ISolutionRepository.FILE_ADD_FAILED;
1286: }
1287: reposFile = new RepositoryFile(fileName, parent, data);
1288: HibernateUtil.commitTransaction();
1289: HibernateUtil.flushSession();
1290: resetRepository();
1291: super .addSolutionFile(baseUrl, path, fileName, data,
1292: overwrite);
1293: return ISolutionRepository.FILE_ADD_SUCCESSFUL;
1294: }
1295: if (!overwrite) {
1296: HibernateUtil.commitTransaction();
1297: HibernateUtil.flushSession();
1298: return ISolutionRepository.FILE_EXISTS;
1299: }
1300: if (hasAccess(reposFile, ACTION_UPDATE)
1301: || isPentahoAdministrator()) {
1302: reposFile.setData(data);
1303: super .addSolutionFile(baseUrl, path, fileName, data,
1304: overwrite);
1305: resetRepository();
1306: } else {
1307: HibernateUtil.commitTransaction();
1308: HibernateUtil.flushSession();
1309: return ISolutionRepository.FILE_ADD_FAILED;
1310: }
1311: HibernateUtil.commitTransaction();
1312: HibernateUtil.flushSession();
1313: return ISolutionRepository.FILE_ADD_SUCCESSFUL;
1314: }
1315:
1316: public int addSolutionFile(String baseUrl, String path,
1317: String fileName, File f, boolean overwrite) {
1318: // baseUrl is ignored
1319: try {
1320: return addSolutionFile(baseUrl, path, fileName, FileHelper
1321: .getBytesFromFile(f), overwrite);
1322: } catch (IOException e) {
1323: e.printStackTrace();
1324: return ISolutionRepository.FILE_ADD_FAILED;
1325: }
1326: }
1327:
1328: public String[] getAllActionSequences() {
1329: Session hibSession = HibernateUtil.getSession();
1330: String nameQuery = "com.pentaho.repository.dbbased.solution.RepositoryFile.findAllActionSequences"; //$NON-NLS-1$
1331: Query qry = hibSession.getNamedQuery(nameQuery).setCacheable(
1332: true);
1333: List rtn = qry.list();
1334: String[] value = new String[rtn.size()];
1335: Iterator iter = rtn.iterator();
1336: int i = 0;
1337: while (iter.hasNext()) {
1338: RepositoryFile file = (RepositoryFile) iter.next();
1339: String path = file.getFullPath();
1340: path = path.substring(repositoryName.length());
1341: value[i++] = path;
1342: }
1343: return value;
1344: }
1345:
1346: public long getSolutionFileLastModified(String path) {
1347: RepositoryFile file = (RepositoryFile) getFileByPath(path);
1348: long mod = -1;
1349: if (file != null) {
1350: mod = file.getLastModified();
1351: }
1352: return mod;
1353: }
1354:
1355: public boolean supportsACLS() {
1356: return true;
1357: }
1358:
1359: }
1360:
1361: /***********************************************************************************************************************
1362: * Old Update DB Repository Classes and Methods *************************** // // This method is no longer used - it's
1363: * here for reference // public List oldloadSolutionFromFileSystem(IPentahoSession pSession, String solutionRoot,
1364: * boolean deleteOrphans) { logger.info(Messages.getString("SolutionRepository.INFO_0001_BEGIN_LOAD_DB_REPOSITORY"));
1365: * //$NON-NLS-1$ // long startTime = System.currentTimeMillis(); File solutionFile = new File(solutionRoot); List
1366: * touched = new ArrayList(); RepositoryFile solution = null; List notTouched = null; if (solutionFile.isDirectory()) {
1367: * String solutionName = solutionFile.getName(); solution = findRootRepositoryByName(solutionName); if (solution ==
1368: * null) { solution = new RepositoryFile(solutionName, null, null, solutionFile.lastModified()); } else if
1369: * (solutionFile.lastModified() != solution.lastModified) { solution.setLastModified(solutionFile.lastModified());
1370: * logger.info(Messages.getString("SolutionRepository.INFO_0002_UPDATED_FOLDER", solution.getFullPath())); //$NON-NLS-1$ }
1371: * touched.add(solution); oldProcessFileSystem(solutionFile, solution, touched); IAclPublisher aclPublisher =
1372: * PentahoSystem.getAclPublisher(pSession); if (aclPublisher != null) { aclPublisher.publishDefaultAcls(solution); }
1373: * HibernateUtil.beginTransaction(); HibernateUtil.makePersistent(solution); notTouched = findNotTouched(touched,
1374: * solution); if (deleteOrphans) { deleteFilesFromSolutionTree(notTouched); } HibernateUtil.commitTransaction(); } else { //
1375: * TODO throw some sort of exception here } getRootSolutionFolder(); // This ensures that the repository name gets set
1376: * correctly. resetRepository(); logger.info(Messages.getString("SolutionRepository.INFO_0003_END_LOAD_DB_REPOSITORY"));
1377: * //$NON-NLS-1$ // long endTime = System.currentTimeMillis(); // System.out.println("*********** Old Repository Load
1378: * Time: " + (endTime - startTime) ); return notTouched; } private List oldProcessFileSystem(File solutionFile,
1379: * RepositoryFile parent, List touched) { // recurse the directories File[] files = solutionFile.listFiles(); for (int i =
1380: * 0; i < files.length; i++) { File aFile = files[i]; if (aFile.isDirectory()) { String directoryName = aFile.getName();
1381: * if (!SolutionReposUtil.ignoreDirectory(directoryName)) { RepositoryFile folder = getFileByPath(parent.getFullPath() +
1382: * RepositoryFile.PATH_SEPERATOR + directoryName); if (folder == null) { folder = new RepositoryFile(directoryName,
1383: * parent, null, aFile.lastModified()); logger.info(Messages.getString("SolutionRepository.INFO_0004_ADDED_FOLDER",
1384: * folder.getFullPath())); //$NON-NLS-1$ } else if (aFile.lastModified() != folder.lastModified) {
1385: * folder.setParent(parent); folder.setFileName(directoryName); folder.setLastModified(aFile.lastModified());
1386: * logger.info(Messages.getString("SolutionRepository.INFO_0005_UPDATED_FOLDER", folder.getFullPath())); //$NON-NLS-1$ }
1387: * touched.add(folder); oldProcessFileSystem(aFile, folder, touched); } } else { // Process other files if
1388: * (!SolutionReposUtil.ignoreFile(aFile.getName())) { try { RepositoryFile reposFile =
1389: * getFileByPath(parent.getFullPath() + RepositoryFile.PATH_SEPERATOR + aFile.getName()); byte[] data =
1390: * getBytesFromFile(aFile); if (reposFile == null) { reposFile = new RepositoryFile(aFile.getName(), parent, data,
1391: * aFile.lastModified()); logger.info(Messages.getString("SolutionRepository.INFO_0006_ADDED_FILE",
1392: * reposFile.getFullPath())); //$NON-NLS-1$ } else if (aFile.lastModified() != reposFile.lastModified) {
1393: * reposFile.setFileName(aFile.getName()); reposFile.setParent(parent); reposFile.setData(data);
1394: * reposFile.setLastModified(aFile.lastModified());
1395: * logger.info(Messages.getString("SolutionRepository.INFO_0007_UPDATED_FILE", reposFile.getFullPath())); //$NON-NLS-1$ }
1396: * touched.add(reposFile); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
1397: * return touched; } private List findNotTouched(List touched, RepositoryFile solution) { List currentFiles = new
1398: * ArrayList(); currentFiles = getAllFilesAsList(solution, currentFiles); Iterator iter = touched.iterator(); while
1399: * (iter.hasNext()) { currentFiles.remove(iter.next()); } return currentFiles; } private List
1400: * getAllFilesAsList(RepositoryFile file, List currentFiles) { currentFiles.add(file); if (file.isDirectory()) {
1401: * Iterator iter = file.getChildrenFiles().iterator(); while (iter.hasNext()) { currentFiles =
1402: * getAllFilesAsList((RepositoryFile) iter.next(), currentFiles); } } return currentFiles; } private void
1403: * deleteFilesFromSolutionTree(List deleteList) { if (deleteList != null) { Iterator iter = deleteList.iterator(); while
1404: * (iter.hasNext()) { RepositoryFile file = (RepositoryFile) iter.next(); RepositoryFile parent = file.getParent(); if
1405: * (parent != null) { // this take care of the case of deleting the // repository completely
1406: * parent.removeChildFile(file); } } } } End Old Update DB Repository Classes and Methods ***************************
1407: **********************************************************************************************************************/
|