/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ro.nextreports.server.dao;
import java.lang.reflect.Field;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.PathNotFoundException;
import javax.jcr.PropertyIterator;
import javax.jcr.RepositoryException;
import javax.jcr.query.QueryResult;
import javax.jcr.version.Version;
import javax.jcr.version.VersionHistory;
import javax.jcr.version.VersionIterator;
import org.apache.jackrabbit.core.NodeImpl;
import org.apache.jackrabbit.core.SessionImpl;
import org.apache.jackrabbit.core.WorkspaceImpl;
import org.apache.jackrabbit.core.config.WorkspaceConfig;
import org.apache.jackrabbit.core.data.GarbageCollector;
import org.apache.jackrabbit.util.ISO9075;
import org.apache.jackrabbit.value.ValueFactoryImpl;
import org.jcrom.JcrDataProviderImpl;
import org.jcrom.JcrFile;
import org.jcrom.JcrMappingException;
import org.jcrom.annotations.JcrIdentifier;
import org.jcrom.annotations.JcrName;
import org.jcrom.annotations.JcrNode;
import org.jcrom.annotations.JcrPath;
import org.jcrom.util.NodeFilter;
import org.jcrom.util.ReflectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Required;
import net.sf.ehcache.Ehcache;
import ro.nextreports.server.StorageConstants;
import ro.nextreports.server.cache.Cache;
import ro.nextreports.server.cache.ehcache.EhCache;
import ro.nextreports.server.domain.Chart;
import ro.nextreports.server.domain.DataSource;
import ro.nextreports.server.domain.DateRange;
import ro.nextreports.server.domain.Entity;
import ro.nextreports.server.domain.Report;
import ro.nextreports.server.domain.ReportRuntimeTemplate;
import ro.nextreports.server.domain.RunReportHistory;
import ro.nextreports.server.domain.SchedulerJob;
import ro.nextreports.server.domain.Settings;
import ro.nextreports.server.domain.User;
import ro.nextreports.server.domain.VersionInfo;
import ro.nextreports.server.exception.DuplicationException;
import ro.nextreports.server.exception.NotFoundException;
import ro.nextreports.server.exception.ReferenceException;
import ro.nextreports.server.util.Pair;
import ro.nextreports.server.util.ServerUtil;
import ro.nextreports.server.util.StorageUtil;
/**
* @author Decebal Suiu
*/
public class JcrStorageDao extends AbstractJcrDao implements StorageDao, InitializingBean {
private static final Logger LOG = LoggerFactory.getLogger(JcrStorageDao.class);
private static final Logger LOG_RUN_HISTORY_FILE = LoggerFactory.getLogger("RUN_HISTORY_FILE");
private Cache entitiesCache;
@Required
public void setCache(Ehcache entitiesCache) {
this.entitiesCache = new EhCache(entitiesCache);
}
public Entity getEntity(String path) throws NotFoundException {
checkPath(path);
return getEntity(getNode(path));
}
public Entity getEntityById(String id) throws NotFoundException {
if (entitiesCache.hasElement(id)) {
return (Entity) entitiesCache.get(id);
}
Node node = checkId(id);
Entity entity = getEntity(node);
entitiesCache.put(id, entity);
return entity;
}
public boolean isSystemEntity(String entityId) throws NotFoundException {
Entity entity = getEntityById(entityId);
return StorageUtil.isSystemPath(entity.getPath());
}
public boolean isEntityFromLoggedRealm(String entityId) throws NotFoundException {
Entity entity = getEntityById(entityId);
String name;
if (entity instanceof User) {
name = entity.getName();
} else {
name = entity.getCreatedBy();
}
return ServerUtil.getRealm().equals(ServerUtil.getRealm(name));
}
public Entity[] getEntityChildren(String path) throws NotFoundException {
checkPath(path);
Node node = getNode(path);
try {
if (!node.hasNodes()) {
return new Entity[0];
}
List<Entity> entities = new ArrayList<Entity>();
NodeIterator nodes = node.getNodes();
while (nodes.hasNext()) {
Entity entity = getEntity(nodes.nextNode());
if (entity != null) {
entities.add(entity);
}
}
return entities.toArray(new Entity[entities.size()]);
} catch (RepositoryException e) {
throw convertJcrAccessException(e);
}
}
// get all children entities without the history nodes (see
// RunReportHistory) which are kept
// under the same node
public Entity[] getBaseEntityChildren(String path) throws NotFoundException {
checkPath(path);
Node node = getNode(path);
try {
if (!node.hasNodes()) {
return new Entity[0];
}
List<Entity> entities = new ArrayList<Entity>();
NodeIterator nodes = node.getNodes();
while (nodes.hasNext()) {
Node child = nodes.nextNode();
if (child.getName().endsWith("_history")) {
continue;
}
Entity entity = getEntity(child);
if (entity != null) {
entities.add(entity);
}
}
return entities.toArray(new Entity[entities.size()]);
} catch (RepositoryException e) {
throw convertJcrAccessException(e);
}
}
public Entity[] getEntityChildrenById(String id) throws NotFoundException {
return getEntityChildrenById(id, 0, Integer.MAX_VALUE);
}
public Entity[] getEntityChildrenById(String id, long firstResult, long maxResults) throws NotFoundException {
// long s1 = System.currentTimeMillis();
// boolean sortable = true;
Node node = checkId(id);
try {
if (!node.hasNodes()) {
return new Entity[0];
}
List<Entity> entities = new ArrayList<Entity>();
// System.out.println("---------->");
// StopWatch watch = new StopWatch();
// watch.start();
NodeIterator nodes = node.getNodes();
// String path = node.getPath();
// String statement = "/jcr:root" + ISO9075.encodePath(path) +
// "//*/)";
// if (sortByName) {
// statement.concat(" ").concat("order by jcr:name ascending");
// }
// System.out.println(">>> " + statement);
// QueryResult queryResult = getTemplate().query(statement);
// NodeIterator nodes = queryResult.getNodes();
// TreeSet<Node> set = new TreeSet<Node>(new Comparator<Node>() {
// @Override
// public int compare(Node n1, Node n2) {
// try {
// String name1 = n1.getName();
// String name2 = n2.getName();
// return name1.compareTo(name2);
// } catch (RepositoryException ex) {
// ex.printStackTrace();
// return 0;
// }
// }
//
// });
// while (nodes.hasNext()) {
// Node nextNode = nodes.nextNode();
// set.add(nextNode);
// }
//
// Iterator<Node> it;
// if (sortable) {
// it = set.iterator();
// } else {
// it = nodes;
// }
NodeIterator it = nodes;
int position = 0;
if (firstResult > 0) {
while (position < firstResult) {
it.next();
position++;
}
// nodes.skip(firstResult);
}
int counter = 0;
while (it.hasNext()) {
if (counter == maxResults) {
break;
}
Node nextNode = it.nextNode();
// watch.suspend();
Entity entity = getEntity(nextNode);
if (entity != null) {
entities.add(entity);
counter++;
}
// watch.resume();
}
// watch.stop();
// System.out.println("t = " + watch.getTime() + " ms");
// System.out.println("< ---------");
// return entities.toArray(new Entity[entities.size()]);
// System.out.println("--> ended in " +
// (System.currentTimeMillis()-s1) + " ms");
return entities.toArray(new Entity[entities.size()]);
} catch (RepositoryException e) {
throw convertJcrAccessException(e);
}
}
public String addEntity(Entity entity) throws DuplicationException {
return addEntity(entity, false);
}
public String addEntity(Entity entity, boolean keepId) throws DuplicationException {
Node parentNode = getNode(StorageUtil.getParentPath(entity.getPath()));
testDuplication(parentNode, entity.getName());
entity.setCreatedDate(new Date());
// maybe a background job (see UserSynchronizerJob) add this entity
String userName = ServerUtil.getUsername();
if (!userName.equals(ServerUtil.UNKNOWN_USER)) {
entity.setCreatedBy(userName);
}
// this method sets also the id on entity (used to add in cache map
// later)
Node node;
if (keepId && (entity.getId() != null)) {
node = addNodeWithUUID(parentNode, entity, entity.getId());
} else {
node = getJcrom().addNode(parentNode, entity);
}
getTemplate().save();
if (isVersionable(node)) {
// create a new version
try {
getSession().getWorkspace().getVersionManager().checkin(entity.getPath());
getSession().getWorkspace().getVersionManager().checkout(entity.getPath());
} catch (RepositoryException e) {
throw convertJcrAccessException(e);
}
}
entitiesCache.put(entity.getId(), entity);
return entity.getId();
}
private Node addNodeWithUUID(Node parentNode, Entity entity, String UUID) {
try {
Node node;
JcrNode jcrNode = ReflectionUtils.getJcrNodeAnnotation(entity.getClass());
// check if we should use a specific node type
if (jcrNode == null || jcrNode.nodeType().equals("nt:unstructured")) {
if (parentNode instanceof NodeImpl) {
node = ((NodeImpl) parentNode).addNodeWithUuid(entity.getName(), UUID);
} else {
node = parentNode.addNode(entity.getName());
}
} else {
if (parentNode instanceof NodeImpl) {
node = ((NodeImpl) parentNode).addNodeWithUuid(entity.getName(), jcrNode.nodeType(), UUID);
} else {
node = parentNode.addNode(entity.getName(), jcrNode.nodeType());
}
}
// add annotated mixin types
if (jcrNode != null && jcrNode.mixinTypes() != null) {
for (String mixinType : jcrNode.mixinTypes()) {
if (node.canAddMixin(mixinType)) {
node.addMixin(mixinType);
}
}
}
// update the object name and path
setNodeName(entity, node.getName());
setNodePath(entity, node.getPath());
if (node.hasProperty("jcr:uuid")) {
setUUID(entity, node.getIdentifier());
}
// map the class name to a property
if (jcrNode != null && !jcrNode.classNameProperty().equals("none")) {
node.setProperty(jcrNode.classNameProperty(), entity.getClass().getCanonicalName());
}
// do update to make internal jcrom business!
getJcrom().updateNode(node, entity);
return node;
} catch (Exception e) {
throw new JcrMappingException("Could not create node from object", e);
}
}
private static Field findAnnotatedField(Object obj, Class annotationClass) {
for (Field field : ReflectionUtils.getDeclaredAndInheritedFields(obj.getClass(), false)) {
if (field.isAnnotationPresent(annotationClass)) {
field.setAccessible(true);
return field;
}
}
return null;
}
static void setNodeName(Object object, String name) throws IllegalAccessException {
findNameField(object).set(object, name);
}
static void setNodePath(Object object, String path) throws IllegalAccessException {
findPathField(object).set(object, path);
}
static void setUUID(Object object, String uuid) throws IllegalAccessException {
Field uuidField = findUUIDField(object);
if (uuidField != null) {
uuidField.set(object, uuid);
}
}
static Field findPathField(Object obj) {
return findAnnotatedField(obj, JcrPath.class);
}
static Field findNameField(Object obj) {
return findAnnotatedField(obj, JcrName.class);
}
static Field findUUIDField(Object obj) {
return findAnnotatedField(obj, JcrIdentifier.class);
}
public void modifyEntity(Entity entity) {
modifyEntity(entity, null);
}
public void modifyEntity(Entity entity, String excludeChildrenName) {
Node node = getNodeById(entity.getId());
entity.setLastUpdatedDate(new Date());
// maybe a background job (see UserSynchronizerJob) modify this entity
String userName = ServerUtil.getUsername();
if (!userName.equals(ServerUtil.UNKNOWN_USER)) {
entity.setLastUpdatedBy(userName);
}
if (excludeChildrenName == null) {
getJcrom().updateNode(node, entity);
} else {
NodeFilter nodeFilter = new NodeFilter("-" + excludeChildrenName, NodeFilter.DEPTH_INFINITE);
getJcrom().updateNode(node, entity, nodeFilter);
}
getTemplate().save();
entitiesCache.put(entity.getId(), entity);
// clear all parents from cache
clearParentsCache(entity);
if (isVersionable(node)) {
// create a new version
try {
getSession().getWorkspace().getVersionManager().checkin(entity.getPath());
getSession().getWorkspace().getVersionManager().checkout(entity.getPath());
} catch (RepositoryException e) {
throw convertJcrAccessException(e);
}
}
}
public void removeEntity(String path) throws ReferenceException {
try {
checkPath(path);
} catch (NotFoundException e) {
return;
}
Node node = getNode(path);
try {
if (node.getReferences().hasNext()) {
throw new ReferenceException("References to this entity exists.");
}
// must remove the versions
// base version can be removed only after the node
VersionHistory versionHistory = null;
String baseVersionName = null;
if (isVersionable(node)) {
versionHistory = getSession().getWorkspace().getVersionManager().getVersionHistory(path);
VersionIterator versions = versionHistory.getAllVersions();
baseVersionName = getSession().getWorkspace().getVersionManager().getBaseVersion(path).getName();
versions.skip(1);
while (versions.hasNext()) {
Version version = versions.nextVersion();
if (!baseVersionName.equals(version.getName())) {
// System.out.println("%%%%% removeVersion : " +
// version.getName());
versionHistory.removeVersion(version.getName());
}
}
}
node.remove();
// @todo if we do not use restore version even this base version can
// be deleted
// @todo but after a restore, it seems there is a cyclic reference
// between base version and root version (???)
// @todo and spring transaction cannot commit
// if (baseVersionName != null) {
// //System.out.println("%%%%% removeBaseVersion : " +
// baseVersionName);
// versionHistory.removeVersion(baseVersionName);
// }
} catch (RepositoryException e) {
throw convertJcrAccessException(e);
}
getTemplate().save();
String id;
try {
id = node.getIdentifier();
} catch (RepositoryException e) {
throw convertJcrAccessException(e);
}
entitiesCache.remove(id);
}
public void removeEntityById(String id) throws NotFoundException {
try {
Node node = checkId(id);
node.remove();
} catch (RepositoryException e) {
throw convertJcrAccessException(e);
}
getTemplate().save();
entitiesCache.remove(id);
}
public List<String> getReferences(String id) {
List<String> result = new ArrayList<String>();
try {
Node node = checkId(id);
PropertyIterator pi = node.getReferences();
while (pi.hasNext()) {
result.add(pi.nextProperty().getParent().getPath());
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
public void renameEntity(String path, String newName) throws NotFoundException, DuplicationException {
checkPath(path);
Node node = getNode(path);
Node parent;
try {
parent = node.getParent();
} catch (RepositoryException e) {
throw convertJcrAccessException(e);
}
testDuplication(parent, newName);
Entity entity = getEntity(node);
entity.setLastUpdatedDate(new Date());
entity.setLastUpdatedBy(ServerUtil.getUsername());
getJcrom().updateNode(node, entity);
getTemplate().rename(node, newName);
getTemplate().save();
entitiesCache.remove(entity.getId());
// clear all children from cache (path is modified!)
clearChildrenCache(entity.getId());
}
public void copyEntity(String sourcePath, String destPath) throws NotFoundException, DuplicationException {
checkPath(sourcePath);
checkPath(destPath);
Node node = getNode(destPath);
testDuplication(node, StorageUtil.getName(sourcePath));
destPath = destPath + StorageConstants.PATH_SEPARATOR + StorageUtil.getName(sourcePath);
try {
getSession().getWorkspace().copy(sourcePath, destPath);
// make sure that any versionable node (report) has its first
// version created
createVersions(destPath);
// cache new entity
getEntity(destPath);
} catch (RepositoryException e) {
throw convertJcrAccessException(e);
}
}
private void createVersions(String path) throws NotFoundException {
checkPath(path);
Node node = getNode(path);
if (isEntityNode(node)) {
if (isVersionable(node)) {
// create a new version
try {
getSession().getWorkspace().getVersionManager().checkin(path);
getSession().getWorkspace().getVersionManager().checkout(path);
} catch (RepositoryException e) {
throw convertJcrAccessException(e);
}
}
for (Entity entity : getEntityChildren(path)) {
createVersions(entity.getPath());
}
}
}
public void moveEntity(String sourcePath, String destPath) throws NotFoundException, DuplicationException {
checkPath(sourcePath);
checkPath(destPath);
Node node = getNode(destPath);
testDuplication(node, StorageUtil.getName(sourcePath));
destPath = destPath + StorageConstants.PATH_SEPARATOR + StorageUtil.getName(sourcePath);
try {
getSession().getWorkspace().move(sourcePath, destPath);
// path changes : remove from cache
Entity entity = getEntity(destPath);
entitiesCache.remove(entity.getId());
// clear all children from cache (path is modified!)
clearChildrenCache(entity.getId());
} catch (RepositoryException e) {
throw convertJcrAccessException(e);
}
}
public Entity[] getEntitiesByClassName(String path, String className) throws NotFoundException {
checkPath(path);
String statement = "/jcr:root" + ISO9075.encodePath(path) + "//*[@className='" + className + "']";
return getEntities(statement);
}
public Entity[] getEntitiesByClassNameForRange(String path, String className, DateRange range)
throws NotFoundException {
// xpath xs:dateTime function has a specific format (see
// getFormattedDate)
// characters that must remain unchanged must be between '' in
// SimpleDateFormat
// SimpleDateFormat format = new
// SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
// this format does not put semicolon in time zone (
// 2012-01-04T23:59:59.999+0200 instead of
// 2012-01-04T23:59:59.999+02:00)
// so we will use getFormattedDate method instead of formatting with a
// SimpleDateFormat
checkPath(path);
StringBuilder sb = new StringBuilder();
sb.append("/jcr:root").append(ISO9075.encodePath(path)).append("//*[@className='").append(className).append("'")
.append(" and @createdDate <= xs:dateTime('").append(getFormattedDate(range.getEndDate())).append("')")
.append(" and @createdDate >= xs:dateTime('").append(getFormattedDate(range.getStartDate()))
.append("')]");
return getEntities(sb.toString());
}
public Entity[] getEntities(String xpath) {
return getEntities(getTemplate().query(xpath));
}
// A date if formatted in JCR like the following :
// 2012-01-04T23:59:59.999+02:00
private String getFormattedDate(Date date) {
String formattedDate = "";
Calendar cal = Calendar.getInstance();
cal.setTime(date);
try {
formattedDate = ValueFactoryImpl.getInstance().createValue(cal).getString();
} catch (Exception e) {
// should never happen
e.printStackTrace();
}
return formattedDate;
}
private Entity[] getEntities(QueryResult queryResult) {
try {
NodeIterator nodes = queryResult.getNodes();
List<Entity> entities = new ArrayList<Entity>();
while (nodes.hasNext()) {
Entity entity = getEntity(nodes.nextNode());
if (entity != null) {
entities.add(entity);
}
}
return entities.toArray(new Entity[entities.size()]);
} catch (RepositoryException e) {
throw convertJcrAccessException(e);
}
}
// clear all parents from cache
private void clearParentsCache(Entity entity) {
try {
String xpath = null;
if (entity instanceof DataSource) {
// find all reports and charts with this DataSource
xpath = "//nextServer//*[@dataSource='" + entity.getId() + "']";
} else if (entity instanceof Report) {
// find all schedulers with this report
xpath = "//nextServer/scheduler/*[@report='" + entity.getId() + "']";
}
if (xpath != null) {
NodeIterator nodes = getTemplate().query(xpath).getNodes();
while (nodes.hasNext()) {
entitiesCache.remove(nodes.nextNode().getIdentifier());
}
}
// if entity is inside a drill down we have to clear the master
// report (with drillDown list)
// first parent is 'drillDownEntities' node; second parent is the
// actual report/chart
if ((entity instanceof Report) || (entity instanceof Chart)) {
xpath = " //nextServer//drillDownEntities/*[@entity='" + entity.getId() + "']";
if (xpath != null) {
NodeIterator nodes = getTemplate().query(xpath).getNodes();
while (nodes.hasNext()) {
entitiesCache.remove(nodes.nextNode().getParent().getParent().getIdentifier());
}
}
}
} catch (RepositoryException e) {
throw convertJcrAccessException(e);
}
}
public void clearUserWidgetData(String widgetId) {
try {
String className = "ro.nextreports.server.domain.UserWidgetParameters";
String xpath = "/jcr:root" + ISO9075.encodePath(StorageConstants.USERS_DATA_ROOT) + "//*[@className='"
+ className + "']";
NodeIterator nodes = getTemplate().query(xpath).getNodes();
while (nodes.hasNext()) {
Node node = nodes.nextNode();
if (node.getName().equals(widgetId)) {
node.remove();
}
}
getTemplate().save();
} catch (RepositoryException e) {
throw convertJcrAccessException(e);
}
}
// TODO remove
public DataSource[] getDataSources() {
Entity[] entities;
try {
entities = getEntitiesByClassName(StorageConstants.DATASOURCES_ROOT, DataSource.class.getName());
} catch (NotFoundException e) {
// never happening
throw new RuntimeException(e);
}
DataSource[] dataSources = new DataSource[entities.length];
System.arraycopy(entities, 0, dataSources, 0, entities.length);
return dataSources;
}
public boolean isEntityReferenced(String path) throws NotFoundException {
checkPath(path);
try {
return getNode(path).getReferences().hasNext();
} catch (RepositoryException e) {
throw convertJcrAccessException(e);
}
}
public boolean entityExists(String path) {
if (!getTemplate().itemExists(path)) {
return false;
}
return isEntityNode(getNode(path));
}
public boolean nodeExists(String path) {
return getTemplate().itemExists(path);
}
public VersionInfo[] getVersionInfos(String id) throws NotFoundException {
// checkPath(path);
Node node = getNodeById(id);
if (!isVersionable(node)) {
// TODO throws an custom exception
return new VersionInfo[0];
}
List<VersionInfo> versionInfos = new ArrayList<VersionInfo>();
try {
VersionHistory versionHistory = getSession().getWorkspace().getVersionManager()
.getVersionHistory(node.getPath());
Version baseVersion = getSession().getWorkspace().getVersionManager().getBaseVersion(node.getPath());
VersionIterator versions = versionHistory.getAllVersions();
versions.skip(1);
while (versions.hasNext()) {
Version version = versions.nextVersion();
NodeIterator nodes = version.getNodes();
while (nodes.hasNext()) {
VersionInfo versionInfo = new VersionInfo();
versionInfo.setName(version.getName());
try {
Entity entity = getEntity(nodes.nextNode());
// after StorageUpdate20 when com.asf.nextserver package
// was renamed with ro.nextreports.server
// all version nodes remained with older className (they
// cannot be changed because they are protected)
// so they cannot be accessed anymore!
if (entity == null) {
continue;
}
String createdBy = entity.getLastUpdatedBy();
if (createdBy == null) {
createdBy = entity.getCreatedBy();
}
versionInfo.setCreatedBy(createdBy);
versionInfo.setCreatedDate(version.getCreated().getTime());
versionInfo.setBaseVersion(baseVersion.getName().equals(version.getName()));
versionInfos.add(versionInfo);
} catch (JcrMappingException ex) {
// getEntity version is not found???
// @todo why?
}
}
}
} catch (RepositoryException e) {
throw convertJcrAccessException(e);
}
return versionInfos.toArray(new VersionInfo[versionInfos.size()]);
}
public Entity getVersion(String id, String versionName) throws NotFoundException {
// checkPath(path);
Node node = getNodeById(id);
if (!isVersionable(node)) {
// TODO throws an custom exception
return null;
}
try {
VersionHistory versionHistory = getSession().getWorkspace().getVersionManager()
.getVersionHistory(node.getPath());
Version baseVersion = getSession().getWorkspace().getVersionManager().getBaseVersion(node.getPath());
Version version = versionHistory.getVersion(versionName);
Entity entity = getEntity(version.getNodes().nextNode());
// @todo another way ?
// hack : otherwise name is "jcr:frozenNode"
entity.setName(StorageUtil.getName(getEntity(node).getPath()));
getJcrom().setBaseVersionInfo(entity, baseVersion.getName(), baseVersion.getCreated());
return entity;
} catch (RepositoryException e) {
throw convertJcrAccessException(e);
}
}
public void restoreVersion(String path, String versionName) throws NotFoundException {
checkPath(path);
Node node = getNode(path);
if (!isVersionable(node)) {
// TODO throws an custom exception
return;
}
try {
getSession().getWorkspace().getVersionManager().restore(node.getPath(), versionName, true);
getSession().getWorkspace().getVersionManager().checkout(node.getPath());
// cache
getEntity(path);
} catch (RepositoryException e) {
throw convertJcrAccessException(e);
}
}
public List<RunReportHistory> getRunHistory(String reportPath) throws NotFoundException {
if (reportPath == null) {
reportPath = StorageConstants.REPORTS_ROOT;
}
checkPath(reportPath);
Entity[] entities = getEntitiesByClassName(reportPath, RunReportHistory.class.getName());
List<RunReportHistory> list = new ArrayList<RunReportHistory>(entities.length);
for (Entity entity : entities) {
list.add((RunReportHistory) entity);
}
return list;
}
public List<ReportRuntimeTemplate> getReportTemplates(String reportPath) throws NotFoundException {
if (reportPath == null) {
return new ArrayList<ReportRuntimeTemplate>();
}
checkPath(reportPath);
Entity[] entities = getEntitiesByClassName(reportPath, ReportRuntimeTemplate.class.getName());
List<ReportRuntimeTemplate> list = new ArrayList<ReportRuntimeTemplate>(entities.length);
for (Entity entity : entities) {
list.add((ReportRuntimeTemplate) entity);
}
return list;
}
public List<ReportRuntimeTemplate> getReportTemplatesById(String reportId) throws NotFoundException {
if (reportId == null) {
return new ArrayList<ReportRuntimeTemplate>();
}
String reportPath = getEntityById(reportId).getPath();
return getReportTemplates(reportPath);
}
public List<RunReportHistory> getRunHistoryForRange(String reportPath, DateRange range) throws NotFoundException {
if (reportPath == null) {
reportPath = StorageConstants.REPORTS_ROOT;
}
checkPath(reportPath);
Entity[] entities = getEntitiesByClassNameForRange(reportPath, RunReportHistory.class.getName(), range);
List<RunReportHistory> list = new ArrayList<RunReportHistory>(entities.length);
for (Entity entity : entities) {
list.add((RunReportHistory) entity);
}
return list;
}
public long deleteRunHistoryForRange(String reportPath, DateRange range, boolean exportToLog)
throws NotFoundException {
if (reportPath == null) {
reportPath = StorageConstants.REPORTS_ROOT;
}
checkPath(reportPath);
StringBuilder sb = new StringBuilder();
sb.append("/jcr:root")//
.append(ISO9075.encodePath(reportPath))//
.append("//*[@className='")//
.append(RunReportHistory.class.getName()).append("'")//
.append(" and @createdDate <= xs:dateTime('").append(getFormattedDate(range.getEndDate())).append("')")//
.append(" and @createdDate >= xs:dateTime('").append(getFormattedDate(range.getStartDate()))//
.append("')")/* .append(" and position < 100") */.append("]");
int count = 0;
String spath = "deleteRunHistoryForRange {" + getFormattedDate(range.getStartDate()) + "}-{"
+ getFormattedDate(range.getEndDate()) + "} ";
try {
LOG.debug(spath + " query this point");
NodeIterator nodes = getTemplate().query(sb.toString()).getNodes();
LOG.debug(spath + "reached this point {" + count + "}");
while (nodes.hasNext()) {
try {
Node node = nodes.nextNode();
// System.err.println("will delete node " +
// node.getIdentifier());
if (exportToLog) {
LOG_RUN_HISTORY_FILE.info(node.toString());
}
node.remove();
entitiesCache.remove(node.getIdentifier());
count++;
if (count % 100 == 0) {
LOG.debug(spath + "count = " + count);
getTemplate().save();
}
} catch (Exception e) {
e.printStackTrace();
}
}
getTemplate().save();
LOG.debug(spath + "after save {" + count + "}");
} catch (RepositoryException e) {
throw convertJcrAccessException(e);
}
return count;
}
public List<RunReportHistory> getRunHistory() {
Entity[] entities;
try {
entities = getEntitiesByClassName(StorageConstants.REPORTS_ROOT, RunReportHistory.class.getName());
} catch (NotFoundException e) {
// never happening
throw new RuntimeException(e);
}
List<RunReportHistory> list = new ArrayList<RunReportHistory>(entities.length);
for (Entity entity : entities) {
list.add((RunReportHistory) entity);
}
return list;
}
// TODO remove
public SchedulerJob[] getSchedulerJobs() throws Exception {
Entity[] entities = getEntitiesByClassName(StorageConstants.SCHEDULER_ROOT, SchedulerJob.class.getName());
SchedulerJob[] schedulerJobs = new SchedulerJob[entities.length];
System.arraycopy(entities, 0, schedulerJobs, 0, entities.length);
return schedulerJobs;
}
public String addOrModifyEntity(Entity entity) {
String id = null;
String path = entity.getPath();
if (entityExists(path)) {
modifyEntity(entity);
id = entity.getId();
} else {
try {
id = addEntity(entity);
} catch (DuplicationException e) {
// never happening
}
}
entitiesCache.put(id, entity);
return id;
}
public String getEntityPath(String id) throws NotFoundException {
if (entitiesCache.hasElement(id)) {
Entity entity = (Entity) entitiesCache.get(id);
return entity.getPath(); // TODO make a review for add entity in
// cache (look at PATH property)
}
try {
Node node = checkId(id);
if (!isEntityNode(node)) {
// TODO may be throw an exception
return null;
}
return node.getPath();
} catch (RepositoryException e) {
throw convertJcrAccessException(e);
}
}
public int countEntityChildrenById(String id) throws NotFoundException {
Node node = checkId(id);
try {
if (!node.hasNodes()) {
return 0;
}
NodeIterator nodes = node.getNodes();
// TODO it's OK ?
return (int) nodes.getSize();
/*
* int count = 0; while (nodes.hasNext()) { Node nextNode =
* nodes.nextNode(); if (isEntityNode(nextNode)) {; count++; } }
*
* return count;
*/
} catch (RepositoryException e) {
throw convertJcrAccessException(e);
}
}
public Cache getEntitiesCache() {
return entitiesCache;
}
private Entity getEntity(Node node) {
if (!isEntityNode(node)) {
String path;
try {
path = node.getPath();
} catch (RepositoryException e) {
throw convertJcrAccessException(e);
}
logger.warn("Node with path " + path + " is not an entity node");
return null;
}
// TODO
String id = null;
try {
id = node.getIdentifier();
} catch (RepositoryException e) {
throw convertJcrAccessException(e);
}
if (entitiesCache.hasElement(id)) {
// System.out.println("+++ getEntity(Node)");
return (Entity) entitiesCache.get(id);
}
Entity entity = getJcrom().fromNode(Entity.class, node);
entitiesCache.put(id, entity);
return entity;
}
private void clearChildrenCache(String entityId) {
Entity[] children = new Entity[0];
try {
children = getEntityChildrenById(entityId);
} catch (NotFoundException e) {
e.printStackTrace();
}
for (Entity entity : children) {
entitiesCache.remove(entity.getId());
clearChildrenCache(entity.getId());
}
}
public void setDefaultProperty(String path, String defaultValue) {
Node node = getNode(path);
try {
node.setProperty("default", defaultValue);
getTemplate().save();
} catch (RepositoryException e) {
throw convertJcrAccessException(e);
}
}
public String getDefaultProperty(String path) throws NotFoundException {
try {
Node node = getNode(path);
return node.getProperty("default").getValue().getString();
} catch (PathNotFoundException e) {
return "";
} catch (RepositoryException e) {
throw convertJcrAccessException(e);
}
}
public byte[] getLogoImage() {
try {
Settings settings = (Settings) getEntity(StorageConstants.SETTINGS_ROOT);
return settings.getLogo().getDataProvider().getBytes();
} catch (NotFoundException e) {
e.printStackTrace();
return new byte[0];
}
}
public void personalizeSettings(String fileName, byte[] content, String theme, String language) {
try {
Settings settings = (Settings) getEntity(StorageConstants.SETTINGS_ROOT);
if (fileName != null) {
JcrFile logo = new JcrFile();
logo.setName(fileName);
logo.setLastModified(Calendar.getInstance());
logo.setPath(StorageUtil.createPath(settings.getPath(), logo.getName()));
logo.setMimeType("image/png");
logo.setDataProvider(new JcrDataProviderImpl(content));
settings.setLogo(logo);
}
settings.setColorTheme(theme);
settings.setLanguage(language);
modifyEntity(settings);
// disable cache
entitiesCache.remove(settings.getId());
} catch (NotFoundException ex) {
// should never happen
ex.printStackTrace();
}
}
public void personalizeTheme(String theme) {
try {
Settings settings = (Settings) getEntity(StorageConstants.SETTINGS_ROOT);
settings.setColorTheme(theme);
modifyEntity(settings);
// disable cache
entitiesCache.remove(settings.getId());
} catch (NotFoundException ex) {
// should never happen
ex.printStackTrace();
}
}
public Settings getSettings() {
try {
return (Settings) getEntity(StorageConstants.SETTINGS_ROOT);
} catch (NotFoundException e) {
// should never happen
e.printStackTrace();
return new Settings();
}
}
public String getDashboardId(String widgetId) throws NotFoundException {
Node node = getNodeById(widgetId);
try {
Node parentNode = node.getParent().getParent();
return parentNode.getIdentifier();
} catch (RepositoryException e) {
throw convertJcrAccessException(e);
}
}
private void experimentalShrinkDerbyDatabase() throws Exception {
String home = null;
try {
WorkspaceImpl workspace = (org.apache.jackrabbit.core.WorkspaceImpl) getSession().getWorkspace();
// String[] workspaceNames =
// workspace.getAccessibleWorkspaceNames();
// for (String str : workspaceNames) {
// System.err.println("str -> " + str);
// }
WorkspaceConfig wc = workspace.getConfig();
home = wc.getHomeDir();
} catch (Exception e) {
e.printStackTrace();
}
// 1 - trebuie sa luam driverul functie de persistencemanager, workspace
// manager
// 2 - trebuie sa gasesc calea unde e baza pt derby
// 3 - calea care e numele default and stuff
// 4 - apel de procedura care distruge stuff
// trebuie sa iau toata 4 tabelele alea si sa dau pe fiecare. (select *
// from sys.systables) si apoi apel de aia de compress one by one
String sql_getTables = "select s.*, (select ss.schemaname from sys.sysschemas ss where ss.schemaid=s.schemaid) as schemaname from sys.systables s "
+ " where s.tablename not like 'SYS%' "
+ " and s.schemaid in (select ss.schemaid from sys.sysschemas ss "
+ " where ss.schemaname not like 'SYS%' " + " and ss.schemaname not like 'NULL%'"
+ " and ss.schemaname not like 'SQL%' )";
Connection con = null;
Statement stm = null;
ResultSet rs = null;
try {
con = getDerbyConnection(home);
stm = con.createStatement();
rs = stm.executeQuery(sql_getTables);
List<Pair<String, String>> lst = new ArrayList<Pair<String, String>>();
while (rs.next()) {
lst.add(new Pair<String, String>(rs.getString("SCHEMANAME"), rs.getString("TABLENAME")));
}
for (Pair<String, String> p : lst) {
try {
LOG.debug("executing for " + p.getFirst() + "." + p.getSecond());
CallableStatement cs = con.prepareCall("CALL SYSCS_UTIL.SYSCS_COMPRESS_TABLE(?, ?, ?)");
cs.setString(1, p.getFirst()/* "US" */);
cs.setString(2, p.getSecond()/* "CUSTOMER" */);
cs.setShort(3, (short) 1);
cs.execute();
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
stm.close();
} catch (Exception e2) {
}
try {
rs.close();
} catch (Exception e2) {
}
try {
con.close();
} catch (Exception e2) {
}
}
}
/** Uses DriverManager. */
private Connection getDerbyConnection(String wkpDir) {
// See your driver documentation for the proper format of this string :
wkpDir = wkpDir.replaceAll("\\\\", "/");
System.err.println(wkpDir);
String DB_CONN_STRING = "jdbc:derby:" + wkpDir // "d:/workspace/workspace-next-work/nextreports-server/data/workspaces/default"
+ "/db;create=false";
// Provided by your driver documentation. In this case, a MySql driver
// is used :
String DRIVER_CLASS_NAME = "org.apache.derby.jdbc.EmbeddedDriver";
String USER_NAME = null;
String PASSWORD = null;
Connection result = null;
try {
Class.forName(DRIVER_CLASS_NAME).newInstance();
} catch (Exception ex) {
LOG.debug("Check classpath. Cannot load db driver: " + DRIVER_CLASS_NAME);
}
try {
result = DriverManager.getConnection(DB_CONN_STRING, USER_NAME, PASSWORD);
} catch (SQLException e) {
LOG.debug("Driver loaded, but cannot connect to db: " + DB_CONN_STRING);
}
return result;
}
public void shrinkDataFolder() {
try {
GarbageCollector gc;
SessionImpl si = (SessionImpl) getTemplate().getSessionFactory().getSession();
gc = si.createDataStoreGarbageCollector();
LOG.debug("GC before mark");
gc.mark();
LOG.debug("GC before sweep");
gc.sweep();
LOG.debug("GC before stopScan");
gc.stopScan();
LOG.debug("GC before rest");
} catch (Exception e) {
e.printStackTrace();
}
try {
experimentalShrinkDerbyDatabase();
} catch (Exception e) {
e.printStackTrace();
}
}
}