/*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License, version 2 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/gpl-2.0.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*/
package org.pentaho.platform.repository.solution;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.nio.channels.FileChannel;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Node;
import org.pentaho.commons.connection.IPentahoStreamSource;
import org.pentaho.platform.api.engine.IActionSequenceResource;
import org.pentaho.platform.api.engine.ICacheManager;
import org.pentaho.platform.api.engine.IDocumentResourceLoader;
import org.pentaho.platform.api.engine.IFileFilter;
import org.pentaho.platform.api.engine.IFileInfo;
import org.pentaho.platform.api.engine.IPentahoInitializer;
import org.pentaho.platform.api.engine.IPentahoSession;
import org.pentaho.platform.api.engine.IPluginManager;
import org.pentaho.platform.api.engine.ISessionContainer;
import org.pentaho.platform.api.engine.ISolutionFile;
import org.pentaho.platform.api.engine.ISolutionFilter;
import org.pentaho.platform.api.repository.ISolutionRepository;
import org.pentaho.platform.engine.core.audit.AuditHelper;
import org.pentaho.platform.engine.core.audit.MessageTypes;
import org.pentaho.platform.engine.core.system.PentahoSystem;
import org.pentaho.platform.engine.services.PentahoMessenger;
import org.pentaho.platform.engine.services.SolutionURIResolver;
import org.pentaho.platform.engine.services.actionsequence.ActionSequenceResource;
import org.pentaho.platform.engine.services.solution.SolutionReposHelper;
import org.pentaho.platform.repository.messages.Messages;
import org.pentaho.platform.repository.solution.filebased.FileSolutionFile;
import org.pentaho.platform.util.StringUtil;
import org.pentaho.platform.util.messages.LocaleHelper;
import org.pentaho.platform.util.web.HttpUtil;
import org.pentaho.platform.util.xml.XmlHelper;
import org.pentaho.platform.util.xml.dom4j.XmlDom4JHelper;
public abstract class SolutionRepositoryBase extends PentahoMessenger implements ISolutionRepository, IPentahoInitializer, ISessionContainer {
private static final long serialVersionUID = 6367444546398801343L;
private IDocumentResourceLoader loader;
public SolutionRepositoryBase() {
super();
loader = new SolutionURIResolver(this);
}
protected IDocumentResourceLoader getResourceLoader() {
return loader;
}
protected static final Log logger = LogFactory.getLog(SolutionRepositoryBase.class);
protected static final int BROWSE_DEPTH = 2;
protected static final String ROOT_NODE_NAME = "repository"; //$NON-NLS-1$
protected static final String LOCATION_ATTR_NAME = "location"; //$NON-NLS-1$
protected static final String EMPTY_STR = ""; //$NON-NLS-1$
protected static final boolean debug = PentahoSystem.debug;
protected static final String ENTRY_NODE_NAME = "entry"; //$NON-NLS-1$
protected static final String TYPE_ATTR_NAME = "type"; //$NON-NLS-1$
protected static final String NAME_ATTR_NAME = "name"; //$NON-NLS-1$
protected static final String DIRECTORY_ATTR = "directory"; //$NON-NLS-1$
protected static final String FILE_ATTR = "file"; //$NON-NLS-1$
protected static final long PUBLISH_TIMEOUT = 1500; // 1.5 seconds
protected static final Map<String, Properties> propertyMap = new HashMap<String, Properties>();
protected static final String LOG_NAME = "SOLUTION-REPOSITORY"; //$NON-NLS-1$
protected static final String PROPERTIES_SUFFIX = ".properties"; //$NON-NLS-1$
protected static final String EMPTY_STRING = ""; //$NON-NLS-1$
/*
* matches 0 or 1 "/" followed by any non-"/" followed by either an end of string or (a "/" followed by 0 or more of anything).
*/
private static final String RE_SYSTEM_PATH = "^[/\\\\]?system($|[/\\\\].*$)"; //$NON-NLS-1$
private static final String RE_SYSTEM_TMP_PATH = "^[/\\\\]?system/tmp($|[/\\\\].*$)"; //$NON-NLS-1$
private static final Pattern SYSTEM_PATH_PATTERN = Pattern.compile(SolutionRepositoryBase.RE_SYSTEM_PATH);
private static final Pattern SYSTEM_TMP_PATH_PATTERN = Pattern.compile(SolutionRepositoryBase.RE_SYSTEM_TMP_PATH);
protected ThreadLocal session = new ThreadLocal();
protected String rootPath;
protected File rootFile;
protected String rootCanonicalName;
@Override
public Log getLogger() {
return SolutionRepositoryBase.logger;
}
protected Locale getLocale() {
return LocaleHelper.getLocale();
}
protected void init() {
rootFile = getFile("", false); //$NON-NLS-1$
rootPath = rootFile.getAbsolutePath() + File.separator;
setLogId(SolutionRepositoryBase.LOG_NAME + ": "); //$NON-NLS-1$
try {
rootCanonicalName = rootFile.getCanonicalPath();
} catch (IOException ex) {
// If we get an IO error here, we have really bad problems.
ex.printStackTrace();
}
}
/**
* NOTE regarding old code: the cacheManager cannot be cached, because it is possible that the SolutionRepository implementation has a scope that is longer
* lived than the cacheManager. When the cacheManager goes out of scope, this class would have maintained a stale reference to a now obsolete cacheManager.
* (sbarkdull)
*
*/
public void init(final IPentahoSession pentahoSession) {
setSession(pentahoSession);
init();
}
protected IPentahoSession getSession() {
Object threadSession = session.get();
return (IPentahoSession) threadSession;
}
public void setSession(final IPentahoSession inSession) {
session.set(inSession);
}
// TODO sbarkdull, this code is very similar to XmlHelper.getLocalizedFile(). they
// likely should be resolved into a single method in an appropriate utility class/package.
protected ISolutionFile getLocalizedFile(final ISolutionFile resourceFile, final int actionOperation) {
String fileName = resourceFile.getFileName();
int idx = fileName.lastIndexOf('.');
String baseName = idx == -1 ? fileName : fileName.substring(0, idx); // These two lines fix an index out of bounds
String extension = idx == -1 ? "" : fileName.substring(idx); // Exception that occurs when a filename has no extension //$NON-NLS-1$
String directory = resourceFile.getSolutionPath();
if (directory.lastIndexOf(fileName) != -1) {
directory = new StringBuffer(directory).delete(directory.lastIndexOf(fileName), directory.length()).toString();
}
if (!directory.endsWith(ISolutionRepository.SEPARATOR + "")) { //$NON-NLS-1$
directory += ISolutionRepository.SEPARATOR;
}
String language = getLocale().getLanguage();
String country = getLocale().getCountry();
String variant = getLocale().getVariant();
ISolutionFile localeFile = null;
if (!variant.equals("")) { //$NON-NLS-1$
localeFile = getFileByPath(directory + baseName + "_" + language + "_" + country + "_" + variant + extension, actionOperation); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
if (localeFile == null) {
localeFile = getFileByPath(directory + baseName + "_" + language + "_" + country + extension, actionOperation); //$NON-NLS-1$//$NON-NLS-2$
}
if (localeFile == null) {
localeFile = getFileByPath(directory + baseName + "_" + language + extension, actionOperation); //$NON-NLS-1$
}
if (localeFile == null) {
localeFile = getFileByPath(directory + baseName + extension, actionOperation);
}
if (localeFile != null) {
return localeFile;
} else {
return resourceFile;
}
}
protected ISolutionFile getFileByPath(final String path, final int actionOperation) {
File file = new File(PentahoSystem.getApplicationContext().getSolutionPath(path));
if ((isPathedUnderSolutionRoot(file)) && (file.exists())) {
return new FileSolutionFile(file, rootFile);
} else {
return null;
}
}
protected boolean isPathedUnderSolutionRoot(String fName) {
return isPathedUnderSolutionRoot(new File(fName));
}
protected boolean isPathedUnderSolutionRoot(File aFile) {
String fc = null;
try {
fc= aFile.getCanonicalPath();
} catch (IOException logitOnly) {
debug("", logitOnly); //$NON-NLS-1$
return false;
}
return ( fc.startsWith(rootCanonicalName) );
}
protected File getFile(final String path, boolean create) {
File f = new File(PentahoSystem.getApplicationContext().getSolutionPath(path));
// Because the startup path calls this method to
// set the rootFile, check if the rootFile is null
if ((rootFile != null) && !(isPathedUnderSolutionRoot(f))) {
return null;
}
if (!f.exists() && !create) {
error(Messages.getInstance().getErrorString("SolutionRepository.ERROR_0001_FILE_DOES_NOT_EXIST", path)); //$NON-NLS-1$
return null;
}
if (!f.exists()) {
f.mkdirs();
}
// TODO: caching
if (SolutionRepositoryBase.debug) {
debug(Messages.getInstance().getErrorString("SolutionRepository.DEBUG_FILE_PATH", f.getAbsolutePath())); //$NON-NLS-1$
}
return f;
}
protected static boolean isSystemPath(final String path) {
Matcher m = SolutionRepositoryBase.SYSTEM_PATH_PATTERN.matcher(path.toLowerCase());
return m.matches();
}
/**
* Returns true if the path is the tmp directory in the system solution.
*/
protected static boolean isSystemTmpPath(final String path) {
Matcher m = SolutionRepositoryBase.SYSTEM_TMP_PATH_PATTERN.matcher(path.toLowerCase());
return m.matches();
}
public InputStream getResourceInputStream(final IActionSequenceResource actionResource, final boolean getLocalizedResource, final int actionOperation) throws FileNotFoundException {
int resourceSource = actionResource.getSourceType();
InputStream inputStream = null;
if (resourceSource == IActionSequenceResource.URL_RESOURCE) {
inputStream = HttpUtil.getURLInputStream(actionResource.getAddress());
} else if ((resourceSource == IActionSequenceResource.SOLUTION_FILE_RESOURCE) || (resourceSource == IActionSequenceResource.FILE_RESOURCE)) {
ISolutionFile solutionFile = getSolutionFile(actionResource, actionOperation);
if (solutionFile == null) {
String msg = "Resource not found: ["+actionResource.getAddress()+"]"; //$NON-NLS-1$ //$NON-NLS-2$
debug(msg);
throw new FileNotFoundException(msg);
} else if (getLocalizedResource) {
solutionFile = getLocalizedFile(solutionFile, actionOperation);
}
inputStream = new ByteArrayInputStream(solutionFile.getData());
}
return inputStream;
}
public void localizeDoc(final Node document, final ISolutionFile file) {
String fileName = file.getFileName();
int dotIndex = fileName.indexOf('.');
String baseName = fileName.substring(0, dotIndex);
// TODO read in nodes from the locale file and use them to override the
// ones in the main document
try {
List nodes = document.selectNodes("descendant::*"); //$NON-NLS-1$
Iterator nodeIterator = nodes.iterator();
while (nodeIterator.hasNext()) {
Node node = (Node) nodeIterator.next();
String name = node.getText();
if (name.startsWith("%") && !node.getPath().endsWith("/text()")) { //$NON-NLS-1$ //$NON-NLS-2$
try {
String localeText = getLocaleString(name, baseName, file, true);
if (localeText != null) {
node.setText(localeText);
}
} catch (Exception e) {
warn(Messages.getInstance().getString("SolutionRepository.WARN_MISSING_RESOURCE_PROPERTY", name.substring(1), baseName, getLocale().toString())); //$NON-NLS-1$
}
}
}
} catch (Exception e) {
error(Messages.getInstance().getErrorString("SolutionRepository.ERROR_0007_COULD_NOT_READ_PROPERTIES", file.getFullPath()), e); //$NON-NLS-1$
}
}
protected String getLocaleString(final String key, final String baseName, final String baseFilePath, final int actionOperation) {
ISolutionFile file = getFileByPath(baseFilePath, actionOperation);
return getLocaleString(key, baseName, file, true);
}
// TODO sbarkdull, needs to be refactored, consider if
// how it should work with/, etc. XmlHelper getLocalizedFile
protected String getLocaleString(final String key, String baseName, final ISolutionFile baseFile, boolean marchUpParents) {
ISolutionFile searchDir = baseFile.retrieveParent();
if (baseFile.isDirectory()) {
searchDir = baseFile;
}
try {
boolean searching = true;
while (searching) {
ISolutionFile[] propertyFiles = searchDir.listFiles(new IFileFilter() {
public boolean accept(ISolutionFile file) {
return file.getFileName().toLowerCase().endsWith(PROPERTIES_SUFFIX);
}
});
ISolutionFile blcv = null;
ISolutionFile blc = null;
ISolutionFile bl = null;
ISolutionFile b = null;
for (ISolutionFile element : propertyFiles) {
if (element.getFileName().equalsIgnoreCase(
baseName + '_' + getLocale().getLanguage() + '_' + getLocale().getCountry() + '_' + getLocale().getVariant() + PROPERTIES_SUFFIX)) {
blcv = element;
}
if (element.getFileName().equalsIgnoreCase(baseName + '_' + getLocale().getLanguage() + '_' + getLocale().getCountry() + PROPERTIES_SUFFIX)) {
blc = element;
}
if (element.getFileName().equalsIgnoreCase(baseName + '_' + getLocale().getLanguage() + PROPERTIES_SUFFIX)) {
bl = element;
}
if (element.getFileName().equalsIgnoreCase(baseName + PROPERTIES_SUFFIX)) {
b = element;
}
}
String localeText = getLocaleText(key, blcv);
if (localeText == null) {
localeText = getLocaleText(key, blc);
if (localeText == null) {
localeText = getLocaleText(key, bl);
if (localeText == null) {
localeText = getLocaleText(key, b);
}
}
}
if (localeText != null) {
return localeText;
}
if (searching && marchUpParents) {
if (!baseName.equals("messages")) { //$NON-NLS-1$
baseName = "messages"; //$NON-NLS-1$
} else {
if (searchDir.isRoot()) {
searching = false;
} else {
searchDir = searchDir.retrieveParent();
}
}
} else if (!marchUpParents) {
searching = false;
}
}
return null;
} catch (Exception e) {
error(Messages.getInstance().getErrorString("SolutionRepository.ERROR_0007_COULD_NOT_READ_PROPERTIES", baseFile.getFullPath()), e); //$NON-NLS-1$
}
return null;
}
protected String getLocaleText(final String key, final ISolutionFile file) throws IOException {
if (file != null) {
Properties p = (Properties) SolutionRepositoryBase.propertyMap.get(file.getFullPath());
if (p == null) {
p = new Properties();
p.load(new ByteArrayInputStream(file.getData()));
SolutionRepositoryBase.propertyMap.put(file.getFullPath(), p);
}
String localeText = p.getProperty(key.substring(1));
if (localeText == null) {
localeText = p.getProperty(key);
}
if (localeText != null) {
return localeText;
}
}
return null;
}
public InputStream getResourceInputStream(final String solutionPath, final boolean getLocalizedResource, final int actionOperation) throws FileNotFoundException {
IActionSequenceResource resource = new ActionSequenceResource("", IActionSequenceResource.SOLUTION_FILE_RESOURCE, "text/xml", //$NON-NLS-1$ //$NON-NLS-2$
solutionPath);
return getResourceInputStream(resource, getLocalizedResource, actionOperation);
}
public Reader getResourceReader(final IActionSequenceResource actionResource, final int actionOperation) throws FileNotFoundException, IOException {
return new InputStreamReader(getResourceInputStream(actionResource, true, actionOperation), LocaleHelper.getSystemEncoding());
}
public Reader getResourceReader(final String solutionPath, final int actionOperation) throws FileNotFoundException, IOException {
IActionSequenceResource resource = new ActionSequenceResource("", IActionSequenceResource.SOLUTION_FILE_RESOURCE, "text/xml", //$NON-NLS-1$ //$NON-NLS-2$
solutionPath);
return getResourceReader(resource, actionOperation);
}
public String getResourceAsString(final IActionSequenceResource actionResource, final int actionOperation) throws IOException {
return new String(getResourceAsBytes(actionResource, true, actionOperation), LocaleHelper.getSystemEncoding());
}
public String getResourceAsString(final String solutionPath, final int actionOperation) throws IOException {
IActionSequenceResource resource = new ActionSequenceResource("", IActionSequenceResource.SOLUTION_FILE_RESOURCE, "text/xml", //$NON-NLS-1$ //$NON-NLS-2$
solutionPath);
return getResourceAsString(resource, actionOperation);
}
public byte[] getResourceAsBytes(final IActionSequenceResource actionResource, final boolean getLocalizedResource, final int actionOperation) throws IOException {
InputStream inputStream = getResourceInputStream(actionResource, getLocalizedResource, actionOperation);
ByteArrayOutputStream bais = new ByteArrayOutputStream();
int numRead = 0;
byte[] buffer = new byte[16384];
while ((numRead = inputStream.read(buffer)) != -1) {
bais.write(buffer, 0, numRead);
}
bais.close();
return bais.toByteArray();
}
public byte[] getResourceAsBytes(final String solutionPath, final boolean getLocalizedResource, final int actionOperation) throws IOException {
IActionSequenceResource resource = new ActionSequenceResource("", IActionSequenceResource.SOLUTION_FILE_RESOURCE, "text/xml", //$NON-NLS-1$ //$NON-NLS-2$
solutionPath);
return getResourceAsBytes(resource, getLocalizedResource, actionOperation);
}
public IPentahoStreamSource getResourceDataSource(final IActionSequenceResource actionResource, final int actionOperation) throws FileNotFoundException {
return new SolutionRepositoryBase.ActionSequenceResourceWrapper(actionResource, getResourceInputStream(actionResource, true, actionOperation));
}
protected static final class ActionSequenceResourceWrapper implements IPentahoStreamSource {
private InputStream inputStream;
private IActionSequenceResource resource;
public ActionSequenceResourceWrapper(IActionSequenceResource actionResource, InputStream iStream) {
super();
assert (actionResource != null);
assert (iStream != null);
this.resource = actionResource;
this.inputStream = iStream;
}
public String getContentType() {
return resource.getMimeType();
}
public InputStream getInputStream() throws IOException {
if (inputStream != null){
if(inputStream.markSupported()) {
try {
inputStream.reset();
}
catch(IOException e) {
//do nothing: a mark has not been set on this stream. This is not an error.
return inputStream;
}
}
}
return inputStream;
}
public String getName() {
return resource.getName();
}
public OutputStream getOutputStream() throws IOException {
return new ByteArrayOutputStream();
}
}
public IPentahoStreamSource getResourceDataSource(final String solutionPath, final int actionOperation) throws FileNotFoundException {
IActionSequenceResource resource = new ActionSequenceResource("", IActionSequenceResource.SOLUTION_FILE_RESOURCE, "text/xml", //$NON-NLS-1$ //$NON-NLS-2$
solutionPath);
return getResourceDataSource(resource, actionOperation);
}
public Document getResourceAsDocument(final String solutionPath, final int actionOperation) throws IOException {
IActionSequenceResource resource = new ActionSequenceResource("", IActionSequenceResource.SOLUTION_FILE_RESOURCE, "text/xml", //$NON-NLS-1$ //$NON-NLS-2$
solutionPath);
return getResourceAsDocument(resource, actionOperation);
}
public Document getResourceAsDocument(final IActionSequenceResource actionResource, final int actionOperation) throws IOException {
Document document = null;
try {
document = XmlDom4JHelper.getDocFromStream(getResourceInputStream(actionResource, true, actionOperation), loader);
} catch (Throwable t) {
error(Messages.getInstance().getErrorString("SolutionRepository.ERROR_0009_INVALID_DOCUMENT", actionResource.getAddress()), t); //$NON-NLS-1$
return null;
}
return document;
}
protected IFileInfo getFileInfo(final String solution, final String path, final String fileName,
final String extension, IPluginManager pluginManager, final int actionOperation) {
IFileInfo fileInfo = null;
String fullPath = solution + ISolutionRepository.SEPARATOR
+ ((StringUtil.isEmpty(path)) ? "" : path + ISolutionRepository.SEPARATOR) + fileName; //$NON-NLS-1$
try {
ISolutionFile file = getFileByPath(fullPath, actionOperation);
InputStream in = getResourceInputStream(fullPath, true, actionOperation);
fileInfo = pluginManager.getFileInfo(extension, getSession(), file, in);
} catch (Exception e) {
error(Messages.getInstance().getErrorString("SolutionRepository.ERROR_0021_FILE_NOT_ADDED", fullPath), e); //$NON-NLS-1$
}
return fileInfo;
}
public Document getSolutions(final int actionOperation) {
return getSolutions(null, null, actionOperation, false);
}
protected List getSolutionNames(final String solutionName, final String pathName, final int actionOperation, final boolean visibleOnly) {
Document solns = getSolutions(solutionName, pathName, actionOperation, visibleOnly);
String xPath = "/repository/file"; //$NON-NLS-1$
return solns.selectNodes(xPath);
}
/**
* Clears cached data for ALL users
*/
public void resetRepository() {
ICacheManager cacheManager = PentahoSystem.getCacheManager(getSession());
if (cacheManager != null) {
cacheManager.killSessionCaches();
cacheManager.clearRegionCache(ISolutionRepository.REPOSITORY_SERVICE_CACHE_REGION);
}
// clear propertymap
SolutionRepositoryBase.propertyMap.clear();
}
public ISolutionFile getRootFolder(final int actionOperation) {
return new FileSolutionFile(rootFile, rootFile);
}
public String getXSLName(final Document document, final String solution, final String inputXSLName) {
String xslName = inputXSLName;
if (solution == null) {
if (xslName == null) {
Node node = document.selectSingleNode("/repository/@displaytype"); //$NON-NLS-1$
if (node != null) {
String displayType = node.getText();
if (displayType.endsWith(".xsl")) { //$NON-NLS-1$
// this folder has a custom XSL
xslName = displayType;
}
}
}
} else {
if (xslName == null) {
Node node = document.selectSingleNode("/files/@displaytype"); //$NON-NLS-1$
if (node != null) {
String displayType = node.getText();
if (displayType.endsWith(".xsl")) { //$NON-NLS-1$
// this folder has a custom XSL
xslName = displayType;
}
}
}
}
return xslName;
}
public Document getNavigationUIDocument(final String solution, final String path, final int actionOperation) {
Document document = this.getSolutions(solution, path, ISolutionRepository.ACTION_EXECUTE, false);
return document;
}
/**
* @return int possible values: ISolutionRepository.FILE_ADD_SUCCESSFUL ISolutionRepository.FILE_EXISTS ISolutionRepository.FILE_ADD_FAILED
*
* TODO mlowery Why can't this delegate to the other addSolutionFile?
*/
public int addSolutionFile(final String baseUrl, String path, final String fileName, final File f, boolean overwrite) {
if (!path.endsWith("/") && !path.endsWith("\\")) { //$NON-NLS-1$ //$NON-NLS-2$
path += File.separator;
}
File fNew = new File(baseUrl + path + fileName);
int status = ISolutionRepository.FILE_ADD_SUCCESSFUL;
if (fNew.exists() && !overwrite) {
status = ISolutionRepository.FILE_EXISTS;
} else {
FileChannel in = null, out = null;
try {
in = new FileInputStream(f).getChannel();
out = new FileOutputStream(fNew).getChannel();
out.transferFrom(in, 0, in.size());
resetRepository();
} catch (Exception e) {
SolutionRepositoryBase.logger.error(e.toString());
status = ISolutionRepository.FILE_ADD_FAILED;
} finally {
try {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
} catch (Exception e) {
// TODO, we should probably log the error, and return a failure status
}
}
}
return status;
}
public int addSolutionFile(final String baseUrl, String path, final String fileName, final byte[] data, boolean overwrite) {
// baseUrl = baseUrl + path;
if (!path.endsWith("/") && !path.endsWith("\\")) { //$NON-NLS-1$//$NON-NLS-2$
path += File.separator;
}
// do not allow publishing to root path
if (path.equals(File.separator)) {
logger.error(Messages.getInstance().getErrorString("SolutionRepository.ERROR_0023_INVALID_PUBLISH_LOCATION_ROOT")); //$NON-NLS-1$
return ISolutionRepository.FILE_ADD_FAILED;
}
File fNew = new File(baseUrl + path + fileName);
int status = ISolutionRepository.FILE_ADD_SUCCESSFUL;
if (fNew.exists() && !overwrite) {
status = ISolutionRepository.FILE_EXISTS;
} else {
FileOutputStream fNewOut = null;
try {
if (!fNew.exists()) {
fNew.getParentFile().mkdirs();
fNew.createNewFile();
}
fNewOut = new FileOutputStream(fNew);
fNewOut.write(data);
resetRepository();
} catch (Exception e) {
status = ISolutionRepository.FILE_ADD_FAILED;
SolutionRepositoryBase.logger.error(e.toString());
} finally {
try {
fNewOut.close();
} catch (Exception e) {
// TODO, we should probably log the error, and return a failure status
}
}
}
return status;
}
public boolean removeSolutionFile(String solutionPath) {
if (isSystemPath(solutionPath)) {
return false;
}
solutionPath = PentahoSystem.getApplicationContext().getSolutionPath(solutionPath);
File deleteFile = new File(solutionPath);
try {
if (deleteFile.exists()) {
if (!deleteFile.isDirectory()) {
boolean deleted = deleteFile.delete();
if (deleted) {
AuditHelper
.audit(
"", getSession().getName(), "", getClass().toString(), "", MessageTypes.UNKNOWN_ENTRY, Messages.getInstance().getString("SOLREPO.AUDIT_DEL_FILE", solutionPath), "", 0.0f, null); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
}
return deleted;
} else { // recursively delete all the files under this directory
// and then delete the directory
return deleteFolder(deleteFile);
}
}
} finally {
resetRepository();
}
return false;
}
/**
* this is the file based removeSolutionFile, used by subclasses
*/
public boolean removeSolutionFile(final String solution, final String path, final String fileName) {
return removeSolutionFile(solution + path + fileName);
}
private boolean deleteFolder(final File dir) {
if (!dir.isDirectory()) {
SolutionRepositoryBase.logger.warn(Messages.getInstance().getString("SolutionRepository.USER_DELETE_FOLDER_WARNING")); //$NON-NLS-1$
return false;
}
String[] files = dir.list();
for (String element : files) {
String filePath = dir.getAbsolutePath() + File.separator + element;
File file = new File(filePath);
if (file.isDirectory()) {
if (deleteFolder(file)) {
AuditHelper
.audit(
"", getSession().getName(), "", getClass().toString(), "", MessageTypes.UNKNOWN_ENTRY, Messages.getInstance().getString("SOLREPO.AUDIT_DEL_FOLDER", filePath), "", 0.0f, null); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
}
} else {
if (file.delete()) {
AuditHelper
.audit(
"", getSession().getName(), "", getClass().toString(), "", MessageTypes.UNKNOWN_ENTRY, Messages.getInstance().getString("SOLREPO.AUDIT_DEL_FILE", filePath), "", 0.0f, null); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
}
}
}
String filePath = dir.getAbsolutePath();
boolean deleted = dir.delete();
if (deleted) {
AuditHelper
.audit(
"", getSession().getName(), "", getClass().toString(), "", MessageTypes.UNKNOWN_ENTRY, Messages.getInstance().getString("SOLREPO.AUDIT_DEL_FOLDER", filePath), "", 0.0f, null); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
}
return deleted;
}
public Document getFullSolutionTree(final int actionOperation, final ISolutionFilter filter) {
return getFullSolutionTree(actionOperation, filter, null);
}
public Document getFullSolutionTree(final int actionOperation, final ISolutionFilter filter, ISolutionFile startingFile) {
startingFile = startingFile == null ? new FileSolutionFile(rootFile, rootFile) : startingFile;
Document document = DocumentHelper.createDocument();
Element root = document.addElement(SolutionReposHelper.TREE_NODE_NAME);
SolutionReposHelper.processSolutionTree(root, startingFile, filter, SolutionReposHelper.ADD_NOTHING_CONTRIBUTOR, actionOperation);
return document;
}
protected boolean isCachingAvailable() {
IPentahoSession pentahoSession = getSession();
ICacheManager cacheManager = PentahoSystem.getCacheManager(pentahoSession);
return (cacheManager != null) && cacheManager.cacheEnabled();
}
/**
* Caches the repository object
*
* @param key -
* String value of the key
* @param value -
* Object referred to by key
*
* @return null if unable to catch otherwise returns the object that was cached
*/
protected Object putRepositoryObjectInCache(final String key, final Object value) {
if (isCachingAvailable()) {
ICacheManager cacheManager = PentahoSystem.getCacheManager(getSession());
cacheManager.putInSessionCache(getSession(), key, value);
return value;
}
return null;
}
/**
* Gets the object from the session cache defined by the parameter key
*
* @param key -
* String value of the key to lookup
*
* @return Object that is referred to by the key. Null if not in the cache or if caching is unavailable
*/
protected Object getRepositoryObjectFromCache(final String key) {
if (isCachingAvailable()) {
ICacheManager cacheManager = PentahoSystem.getCacheManager(getSession());
return cacheManager.getFromSessionCache(getSession(), key);
}
return null;
}
public ISolutionFile getSolutionFile(final String path, final int actionOperation) {
ISolutionFile solutionFile = null;
if (!SolutionRepositoryBase.isSystemPath(path)) {
// Not checking here because the underlying
// has the check.
solutionFile = getFileByPath(path, actionOperation);
} else {
String solutionPath = PentahoSystem.getApplicationContext().getSolutionPath(path);
if ((isPathedUnderSolutionRoot(solutionPath))) {
solutionFile = new FileSolutionFile(new File(solutionPath), rootFile);
}
}
return solutionFile;
}
public ISolutionFile getSolutionFile(final IActionSequenceResource actionResource, final int actionOperation) {
ISolutionFile solutionFile = null;
int resourceSource = actionResource.getSourceType();
String realPath = null;
if (resourceSource == IActionSequenceResource.SOLUTION_FILE_RESOURCE) {
realPath = actionResource.getAddress();
solutionFile = getSolutionFile(realPath, actionOperation);
} else if (resourceSource == IActionSequenceResource.FILE_RESOURCE) {
realPath = actionResource.getAddress();
if ((isPathedUnderSolutionRoot(realPath))) {
solutionFile = new FileSolutionFile(new File(realPath), rootFile);
}
}
if ((solutionFile == null) || !solutionFile.exists()) {
solutionFile = null;
}
return solutionFile;
}
public ISolutionFile createFolder(final File newFolder) throws IOException {
if (!(isPathedUnderSolutionRoot(newFolder))) {
throw new IOException(Messages.getInstance().getErrorString("SolutionRepository.ERROR_0021_FILE_NOT_ADDED", newFolder.getName())); //$NON-NLS-1$
}
newFolder.mkdirs();
FileSolutionFile fsf = new FileSolutionFile(newFolder, rootFile);
return fsf;
}
public String getLocalizedFileProperty(final ISolutionFile resourceFile, final String key, final int actionOperation) {
if (!hasAccess(resourceFile, actionOperation)) {
return null;
}
// look for .properties file for this file
String fileName = resourceFile.getFileName();
int idx = fileName.lastIndexOf('.');
String baseName = idx == -1 ? fileName : fileName.substring(0, idx);
String localizedName;
if (resourceFile.isDirectory()) {
// directory info is stored in index.properties files
// name.startsWith("%")
// look in index.xml for attributes first, if they start with % then do getLocaleString
ISolutionFile possibleIndexFiles[] = resourceFile.listFiles(new IFileFilter() {
public boolean accept(ISolutionFile file) {
if (file.getFileName().equals("index.xml")) { //$NON-NLS-1$
return true;
}
return false;
}
});
String value = null;
if (possibleIndexFiles.length > 0) {
// figure out what the XML string says the encoding is
String xml = new String(possibleIndexFiles[0].getData());
Document document = null;
try {
document = XmlDom4JHelper.getDocFromString(xml, this.getResourceLoader());
value = document.selectSingleNode("/index/" + key).getText(); //$NON-NLS-1$
} catch (Throwable t) {
t.printStackTrace();
value = null;
}
}
if ((value == null) || "".equals(value)) { //$NON-NLS-1$
localizedName = getLocaleString(key, "index", resourceFile, false); //$NON-NLS-1$
} else if (value.startsWith("%")) { //$NON-NLS-1$
localizedName = getLocaleString(value.substring(1), "index", resourceFile, false); //$NON-NLS-1$
} else {
localizedName = value;
}
} else {
// if the file is an xaction/url we need to open those files to check for the property
String value = null;
// figure out what the XML string says the encoding is
if (resourceFile.getFileName().endsWith(".xaction")) { //$NON-NLS-1$
String xml = new String(resourceFile.getData());
Document document = null;
try {
document = XmlDom4JHelper.getDocFromString(xml, this.getResourceLoader());
value = document.selectSingleNode("/action-sequence/" + key).getText(); //$NON-NLS-1$
} catch (Throwable t) {
value = null;
}
}
if ((value == null) || "".equals(value)) { //$NON-NLS-1$
localizedName = getLocaleString(key, baseName, resourceFile, false);
} else if (value.startsWith("%")) { //$NON-NLS-1$
// regular file info is stored in basename.properties files
localizedName = getLocaleString(value.substring(1), baseName, resourceFile, false);
} else {
localizedName = value;
}
}
return localizedName;
}
protected String buildDirectoryPath(final String solution, final String path, final String action) {
String localDirStr = EMPTY_STRING;
localDirStr += ISolutionRepository.SEPARATOR;
if ((solution != null) && (solution.length() > 0)) {
localDirStr += solution;
if ((path != null) && (path.length() > 0)) {
localDirStr += ISolutionRepository.SEPARATOR;
localDirStr += path;
}
}
if ((action != null) && (action.length() > 0)) {
String seperator = new String() + ISolutionRepository.SEPARATOR;
if (!localDirStr.endsWith(seperator)) {
localDirStr += ISolutionRepository.SEPARATOR;
}
localDirStr += action;
}
return localDirStr;
}
protected String buildDirectoryPath(final String repositoryName, final String path) {
String seperator = null;
seperator += ISolutionRepository.SEPARATOR;
int initialStartingPoint = path.indexOf(repositoryName.replaceAll(seperator, EMPTY_STRING));
if(initialStartingPoint >=0) {
int start = path.indexOf(ISolutionRepository.SEPARATOR, initialStartingPoint);
if(start >= 0) {
return path.substring(start + 1, path.length());
}
}
return path;
}
// TODO sbarkdull, refactor, this should should be in the XmlHelper class
// maybe rename getNodeTextOrDefault
protected String getValue(final Document doc, final String xPath, final String defaultValue) {
if (doc != null) {
Node node = doc.selectSingleNode(xPath);
if (node == null) {
return defaultValue;
}
return node.getText();
}
return defaultValue;
}
@Deprecated
public String[] getAllActionSequences() {
return getAllActionSequences(ISolutionRepository.ACTION_EXECUTE);
}
@Deprecated
public String getLocalizedFileProperty(ISolutionFile resourceFile, String key) {
return getLocalizedFileProperty(resourceFile, key, ISolutionRepository.ACTION_EXECUTE);
}
@Deprecated
public byte[] getResourceAsBytes(String solutionPath, boolean getLocalizedResource) throws IOException {
return getResourceAsBytes(solutionPath, getLocalizedResource, ISolutionRepository.ACTION_EXECUTE);
}
@Deprecated
public byte[] getResourceAsBytes(IActionSequenceResource actionResource, boolean getLocalizedResource)
throws IOException {
return getResourceAsBytes(actionResource, getLocalizedResource, ISolutionRepository.ACTION_EXECUTE);
}
@Deprecated
public Document getResourceAsDocument(String solutionPath) throws IOException {
return getResourceAsDocument(solutionPath, ISolutionRepository.ACTION_EXECUTE);
}
@Deprecated
public Document getResourceAsDocument(IActionSequenceResource actionResource) throws IOException {
return getResourceAsDocument(actionResource, ISolutionRepository.ACTION_EXECUTE);
}
@Deprecated
public String getResourceAsString(IActionSequenceResource actionResource) throws IOException {
return getResourceAsString(actionResource, ISolutionRepository.ACTION_EXECUTE);
}
@Deprecated
public String getResourceAsString(String solutionPath) throws IOException {
return getResourceAsString(solutionPath, ISolutionRepository.ACTION_EXECUTE);
}
@Deprecated
public IPentahoStreamSource getResourceDataSource(String solutionPath) throws FileNotFoundException {
return getResourceDataSource(solutionPath, ISolutionRepository.ACTION_EXECUTE);
}
@Deprecated
public IPentahoStreamSource getResourceDataSource(IActionSequenceResource actionResource)
throws FileNotFoundException {
return getResourceDataSource(actionResource, ISolutionRepository.ACTION_EXECUTE);
}
@Deprecated
public InputStream getResourceInputStream(IActionSequenceResource actionResource, boolean getLocalizedResource)
throws FileNotFoundException {
return getResourceInputStream(actionResource, getLocalizedResource, ISolutionRepository.ACTION_EXECUTE);
}
@Deprecated
public InputStream getResourceInputStream(String solutionPath, boolean getLocalizedResource)
throws FileNotFoundException {
return getResourceInputStream(solutionPath, getLocalizedResource, ISolutionRepository.ACTION_EXECUTE);
}
@Deprecated
public Reader getResourceReader(IActionSequenceResource actionResource) throws FileNotFoundException, IOException {
return getResourceReader(actionResource, ISolutionRepository.ACTION_EXECUTE);
}
@Deprecated
public Reader getResourceReader(String solutionPath) throws FileNotFoundException, IOException {
return getResourceReader(solutionPath, ISolutionRepository.ACTION_EXECUTE);
}
@Deprecated
public ISolutionFile getSolutionFile(String path) {
return getSolutionFile(path, ISolutionRepository.ACTION_EXECUTE);
}
@Deprecated
public ISolutionFile getSolutionFile(IActionSequenceResource actionResource) {
return getSolutionFile(actionResource, ISolutionRepository.ACTION_EXECUTE);
}
@Deprecated
public long getSolutionFileLastModified(String path) {
return getSolutionFileLastModified(path, ISolutionRepository.ACTION_EXECUTE);
}
@Deprecated
public boolean resourceExists(String solutionPath) {
return resourceExists(solutionPath, ISolutionRepository.ACTION_EXECUTE);
}
@Deprecated
public long resourceSize(String solutionPath) {
return resourceSize(solutionPath, ISolutionRepository.ACTION_EXECUTE);
}
/**
* {@inheritDoc}
*/
@Deprecated
public ISolutionFile getFileByPath(String path) {
return getSolutionFile(path, ISolutionRepository.ACTION_EXECUTE);
}
}