blob: 4020704a07654bbe75fe3d9915a2dcaa69027cf7 [file] [log] [blame]
/*
* 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 org.apache.sling.event.dea.impl;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.sling.api.resource.PersistenceException;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.api.resource.ValueMap;
public abstract class ResourceHelper {
public static final String PROPERTY_MARKER_READ_ERROR_LIST = ResourceHelper.class.getName() + "/ReadErrorList";
public static Map<String, Object> cloneValueMap(final ValueMap vm) throws InstantiationException {
List<Exception> hasReadError = null;
try {
final Map<String, Object> result = new HashMap<String, Object>(vm);
for(final Map.Entry<String, Object> entry : result.entrySet()) {
if ( entry.getValue() instanceof InputStream ) {
final Object value = vm.get(entry.getKey(), Serializable.class);
if ( value != null ) {
entry.setValue(value);
} else {
if ( hasReadError == null ) {
hasReadError = new ArrayList<Exception>();
}
final int count = hasReadError.size();
// let's find out which class might be missing
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream((InputStream)entry.getValue());
ois.readObject();
} catch (final ClassNotFoundException cnfe) {
hasReadError.add(new Exception("Unable to deserialize property '" + entry.getKey() + "'", cnfe));
} catch (final IOException ioe) {
hasReadError.add(new Exception("Unable to deserialize property '" + entry.getKey() + "'", ioe));
} finally {
if ( ois != null ) {
try {
ois.close();
} catch (IOException ignore) {
// ignore
}
}
}
if ( hasReadError.size() == count ) {
hasReadError.add(new Exception("Unable to deserialize property '" + entry.getKey() + "'"));
}
}
}
}
if ( hasReadError != null ) {
result.put(PROPERTY_MARKER_READ_ERROR_LIST, hasReadError);
}
return result;
} catch ( final IllegalArgumentException iae) {
// the JCR implementation might throw an IAE if something goes wrong
throw (InstantiationException)new InstantiationException(iae.getMessage()).initCause(iae);
}
}
public static ValueMap getValueMap(final Resource resource) throws InstantiationException {
final ValueMap vm = ResourceUtil.getValueMap(resource);
// trigger full loading
try {
vm.size();
} catch ( final IllegalArgumentException iae) {
// the JCR implementation might throw an IAE if something goes wrong
throw (InstantiationException)new InstantiationException(iae.getMessage()).initCause(iae);
}
return vm;
}
/**
* A batch resource remover deletes resources in batches. Once the batch
* size (threshold) is reached, an intermediate commit is performed. Resource
* trees are deleted resource by resource starting with the deepest children first.
* Once all resources have been passed to the batch resource remover, a final
* commit needs to be called on the resource resolver.
*/
public static class BatchResourceRemover {
private final int max;
private int count;
public BatchResourceRemover(final int batchSize) {
this.max = (batchSize < 1 ? 50 : batchSize);
}
public void delete(final Resource rsrc)
throws PersistenceException {
final ResourceResolver resolver = rsrc.getResourceResolver();
for(final Resource child : rsrc.getChildren()) {
delete(child);
}
resolver.delete(rsrc);
count++;
if ( count >= max ) {
resolver.commit();
count = 0;
}
}
}
/**
* Create a batch resource remover.
* A batch resource remove can be used to delete resources in batches.
* Once the passed in threshold of deleted resources is reached, an intermediate
* commit is called on the resource resolver. In addition the batch remover
* deletes a resource recursively.
* Once all resources to delete are passed to the remover, a final commit needs
* to be call on the resource resolver.
* @param threshold The threshold for the intermediate saves.
* @return A new batch resource remover.
*/
public static BatchResourceRemover getBatchResourceRemover(final int threshold) {
return new BatchResourceRemover(threshold);
}
}