You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by th...@apache.org on 2007/09/06 12:07:46 UTC
svn commit: r573209 - in /jackrabbit/trunk/jackrabbit-core: ./
src/main/java/org/apache/jackrabbit/core/
src/main/java/org/apache/jackrabbit/core/config/
src/main/java/org/apache/jackrabbit/core/data/
src/main/java/org/apache/jackrabbit/core/persistenc...
Author: thomasm
Date: Thu Sep 6 03:07:41 2007
New Revision: 573209
URL: http://svn.apache.org/viewvc?rev=573209&view=rev
Log:
JCR-926: configuration for data store in repository.xml
Added:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/DataStoreConfig.java (with props)
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInResource.java (with props)
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInTempFile.java
Modified:
jackrabbit/trunk/jackrabbit-core/ (props changed)
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfig.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfigurationParser.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/DataStore.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/FileDataStore.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/BundleBinding.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/ItemStateBinding.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/InternalValue.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/BufferedStringValue.java
Propchange: jackrabbit/trunk/jackrabbit-core/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Thu Sep 6 03:07:41 2007
@@ -1,11 +1,12 @@
-target
-*.log
-*.iws
-*.ipr
-*.iml
-junit*.properties
-.settings
-.classpath
-.project
-*.xml.md5
-*-pom-snapshot-version
+target
+*.log
+*.iws
+*.ipr
+*.iml
+junit*.properties
+.settings
+.classpath
+.project
+*.xml.md5
+*-pom-snapshot-version
+.checkstyle
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java?rev=573209&r1=573208&r2=573209&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java Thu Sep 6 03:07:41 2007
@@ -29,6 +29,7 @@
import org.apache.jackrabbit.core.cluster.UpdateEventChannel;
import org.apache.jackrabbit.core.cluster.UpdateEventListener;
import org.apache.jackrabbit.core.config.ClusterConfig;
+import org.apache.jackrabbit.core.config.DataStoreConfig;
import org.apache.jackrabbit.core.config.FileSystemConfig;
import org.apache.jackrabbit.core.config.LoginModuleConfig;
import org.apache.jackrabbit.core.config.PersistenceManagerConfig;
@@ -36,7 +37,6 @@
import org.apache.jackrabbit.core.config.VersioningConfig;
import org.apache.jackrabbit.core.config.WorkspaceConfig;
import org.apache.jackrabbit.core.data.DataStore;
-import org.apache.jackrabbit.core.data.FileDataStore;
import org.apache.jackrabbit.core.fs.BasedFileSystem;
import org.apache.jackrabbit.core.fs.FileSystem;
import org.apache.jackrabbit.core.fs.FileSystemException;
@@ -58,6 +58,7 @@
import org.apache.jackrabbit.core.state.ManagedMLRUItemStateCacheFactory;
import org.apache.jackrabbit.core.state.SharedItemStateManager;
import org.apache.jackrabbit.core.util.RepositoryLock;
+import org.apache.jackrabbit.core.value.InternalValue;
import org.apache.jackrabbit.core.version.VersionManager;
import org.apache.jackrabbit.core.version.VersionManagerImpl;
import org.apache.jackrabbit.name.NamespaceResolver;
@@ -248,8 +249,6 @@
throw new RepositoryException(msg, fse);
}
metaDataStore = new BasedFileSystem(repStore, fsRootPath);
- dataStore =
- new FileDataStore(new File(repConfig.getHomeDir(), "datastore"));
// init root node uuid
rootNodeId = loadRootNodeId(metaDataStore);
@@ -262,6 +261,13 @@
// create registries
nsReg = createNamespaceRegistry(new BasedFileSystem(repStore, "/namespaces"));
ntReg = createNodeTypeRegistry(nsReg, new BasedFileSystem(repStore, "/nodetypes"));
+
+ if (repConfig.getDataStoreConfig() != null) {
+ assert InternalValue.USE_DATA_STORE;
+ dataStore = createDataStore();
+ } else {
+ dataStore = null;
+ }
// init workspace configs
Iterator iter = repConfig.getWorkspaceConfigs().iterator();
@@ -627,6 +633,18 @@
} catch (Exception e) {
throw new RepositoryException(e);
}
+ }
+
+ /**
+ * Create a data store object using the data store configuration.
+ *
+ * @return the data store object
+ */
+ protected DataStore createDataStore() throws RepositoryException {
+ DataStoreConfig dsc = repConfig.getDataStoreConfig();
+ DataStore dataStore = (DataStore) dsc.newInstance();
+ dataStore.init(repConfig.getHomeDir());
+ return dataStore;
}
protected NamespaceRegistryImpl getNamespaceRegistry() {
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/DataStoreConfig.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/DataStoreConfig.java?rev=573209&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/DataStoreConfig.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/DataStoreConfig.java Thu Sep 6 03:07:41 2007
@@ -0,0 +1,17 @@
+package org.apache.jackrabbit.core.config;
+
+/**
+ * Data store configuration.
+ */
+public class DataStoreConfig extends BeanConfig {
+
+ /**
+ * Creates a data store configuration object from the given bean configuration.
+ *
+ * @param config bean configuration
+ */
+ public DataStoreConfig(BeanConfig config) {
+ super(config);
+ }
+
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/DataStoreConfig.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfig.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfig.java?rev=573209&r1=573208&r2=573209&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfig.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfig.java Thu Sep 6 03:07:41 2007
@@ -216,6 +216,11 @@
* Optional cluster configuration.
*/
private final ClusterConfig cc;
+
+ /**
+ * Optional data store configuration
+ */
+ private final DataStoreConfig dataStoreConfig;
/**
* Creates a repository configuration object.
@@ -237,7 +242,7 @@
String workspaceDirectory, String workspaceConfigDirectory,
String defaultWorkspace, int workspaceMaxIdleTime,
Element template, VersioningConfig vc, SearchConfig sc,
- ClusterConfig cc, RepositoryConfigurationParser parser) {
+ ClusterConfig cc, DataStoreConfig dataStoreConfig, RepositoryConfigurationParser parser) {
workspaces = new HashMap();
this.home = home;
this.sec = sec;
@@ -250,6 +255,7 @@
this.vc = vc;
this.sc = sc;
this.cc = cc;
+ this.dataStoreConfig = dataStoreConfig;
this.parser = parser;
}
@@ -742,4 +748,13 @@
public ClusterConfig getClusterConfig() {
return cc;
}
+
+ /**
+ * Returns the data store configuration. Returns <code>null</code> if data store
+ * has not been configured.
+ */
+ public DataStoreConfig getDataStoreConfig() {
+ return dataStoreConfig;
+ }
}
+
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfigurationParser.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfigurationParser.java?rev=573209&r1=573208&r2=573209&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfigurationParser.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfigurationParser.java Thu Sep 6 03:07:41 2007
@@ -78,6 +78,9 @@
/** Name of the journal configuration element. */
public static final String JOURNAL_ELEMENT = "Journal";
+
+ /** Name of the data store configuration element. */
+ public static final String DATA_STORE_ELEMENT = "DataStore";
/** Name of the persistence manager configuration element. */
public static final String PERSISTENCE_MANAGER_ELEMENT =
@@ -216,10 +219,13 @@
// Optional journal configuration
ClusterConfig cc = parseClusterConfig(root);
+
+ // Optional data store configuration
+ DataStoreConfig dsc = parseDataStoreConfig(root);
return new RepositoryConfig(home, securityConfig, fsc,
workspaceDirectory, workspaceConfigDirectory, defaultWorkspace,
- maxIdleTime, template, vc, sc, cc, this);
+ maxIdleTime, template, vc, sc, cc, dsc, this);
}
/**
@@ -513,6 +519,37 @@
return new JournalConfig(
parseBeanConfig(cluster, JOURNAL_ELEMENT));
}
+
+ /**
+ * Parses data store configuration. Data store configuration uses the following format:
+ * <pre>
+ * <DataStore class="...">
+ * <param name="..." value="...">
+ * ...
+ * </DataStore>
+ * </pre>
+ * <p/>
+ * <code>DataStore</code> is a {@link #parseBeanConfig(Element,String) bean configuration}
+ * element.
+ *
+ * @param cluster parent cluster element
+ * @return journal configuration, or <code>null</code>
+ * @throws ConfigurationException if the configuration is broken
+ */
+ protected DataStoreConfig parseDataStoreConfig(Element parent)
+ throws ConfigurationException {
+ NodeList children = parent.getChildNodes();
+ for (int i = 0; i < children.getLength(); i++) {
+ Node child = children.item(i);
+ if (child.getNodeType() == Node.ELEMENT_NODE
+ && DATA_STORE_ELEMENT.equals(child.getNodeName())) {
+ DataStoreConfig cfg = new DataStoreConfig(parseBeanConfig(
+ parent, DATA_STORE_ELEMENT));
+ return cfg;
+ }
+ }
+ return null;
+ }
/**
* Parses the PersistenceManager config.
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/DataStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/DataStore.java?rev=573209&r1=573208&r2=573209&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/DataStore.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/DataStore.java Thu Sep 6 03:07:41 2007
@@ -92,5 +92,12 @@
* Get all identifiers.
*/
Iterator getAllIdentifiers();
+
+ /**
+ * Initialized the data store
+ *
+ * @param homeDir the home directory of the repository
+ */
+ void init(String homeDir);
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/FileDataStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/FileDataStore.java?rev=573209&r1=573208&r2=573209&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/FileDataStore.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/FileDataStore.java Thu Sep 6 03:07:41 2007
@@ -30,6 +30,15 @@
/**
* Simple file-based data store. Data records are stored as normal files
* named using a message digest of the contained binary stream.
+ *
+ * Configuration:<br>
+ * <ul>
+ * <li><param name="className" value="org.apache.jackrabbit.core.data.FileDataStore"/>
+ * <li><param name="{@link #setPath(String) path}" value="/data/datastore"/>
+ * </ul>
+ *
+ * <p>
+ * If the directory is not set, the directory <repository home>/repository/datastore is used.
* <p>
* A three level directory structure is used to avoid placing too many
* files in a single directory. The chosen structure is designed to scale
@@ -61,15 +70,34 @@
* The directory that contains all the data record files. The structure
* of content within this directory is controlled by this class.
*/
- private final File directory;
+ private File directory;
+
+ /**
+ * The name of the directory that contains all the data record files. The structure
+ * of content within this directory is controlled by this class.
+ */
+ private String path;
/**
- * Creates a data store based on the given directory.
+ * Creates a uninitialized data store.
*
- * @param directory data store directory
*/
- public FileDataStore(File directory) {
- this.directory = directory;
+ public FileDataStore() {
+ }
+
+ /**
+ * Initialized the data store.
+ * If the path is not set, <repository home>/repository/datastore is used.
+ * This directory is automatically created if it does not yet exist.
+ *
+ * @param config the repository configuration
+ */
+ public void init(String homeDir) {
+ if (path == null) {
+ path = homeDir + "/repository/datastore";
+ }
+ directory = new File(path);
+ directory.mkdirs();
}
/**
@@ -132,6 +160,9 @@
}
if (!file.exists()) {
temporary.renameTo(file);
+ if (!file.exists()) {
+ throw new IOException("Can not rename " + temporary.getAbsolutePath() + " to " + file.getAbsolutePath() + " (media read only?)");
+ }
} else {
long now = System.currentTimeMillis();
if (file.lastModified() < now) {
@@ -247,6 +278,24 @@
}
}
return identifiers.iterator();
+ }
+
+ /**
+ * Get the name of the directory where this data store keeps the files.
+ *
+ * @return the full path name
+ */
+ public String getPath() {
+ return path;
+ }
+
+ /**
+ * Set the name of the directory where this data store keeps the files.
+ *
+ * @param path the full path name
+ */
+ public void setPath(String directoryName) {
+ this.path = directoryName;
}
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/BundleBinding.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/BundleBinding.java?rev=573209&r1=573208&r2=573209&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/BundleBinding.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/BundleBinding.java Thu Sep 6 03:07:41 2007
@@ -288,7 +288,7 @@
writeModCount(out, bundle.getModCount());
// set size of bundle
- bundle.setSize(out.size()-size);
+ bundle.setSize(out.size() - size);
}
/**
@@ -305,7 +305,7 @@
// type and modcount
int type = in.readInt();
entry.setModCount((short) ((type >> 16) & 0x0ffff));
- type&=0x0ffff;
+ type &= 0x0ffff;
entry.setType(type);
// multiValued
@@ -369,8 +369,8 @@
int len = in.readInt();
byte[] bytes = new byte[len];
int pos = 0;
- while (pos<len) {
- pos+= in.read(bytes, pos, len-pos);
+ while (pos < len) {
+ pos += in.read(bytes, pos, len - pos);
}
val = InternalValue.valueOf(new String(bytes, "UTF-8"), type);
}
@@ -522,8 +522,8 @@
try {
byte[] bytes = new byte[len];
int pos = 0;
- while (pos<len) {
- pos+= in.read(bytes, pos, len-pos);
+ while (pos < len) {
+ pos += in.read(bytes, pos, len - pos);
}
log.info(" string: " + new String(bytes, "UTF-8"));
} catch (IOException e) {
@@ -558,7 +558,7 @@
InternalValue val = values[i];
switch (state.getType()) {
case PropertyType.BINARY:
- if(InternalValue.USE_DATA_STORE) {
+ if (InternalValue.USE_DATA_STORE && dataStore != null) {
out.writeInt(-2);
out.writeUTF(val.toString());
break;
@@ -622,7 +622,7 @@
try {
int pos = 0;
while (pos < size) {
- int n = in.read(data, pos, (int) size-pos);
+ int n = in.read(data, pos, (int) size - pos);
if (n < 0) {
throw new EOFException();
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/ItemStateBinding.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/ItemStateBinding.java?rev=573209&r1=573208&r2=573209&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/ItemStateBinding.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/ItemStateBinding.java Thu Sep 6 03:07:41 2007
@@ -64,12 +64,12 @@
/**
* serialization version 1
*/
- public final static int VERSION_1 = 1;
+ public static final int VERSION_1 = 1;
/**
* current version
*/
- public final static int VERSION_CURRENT = VERSION_1;
+ public static final int VERSION_CURRENT = VERSION_1;
/**
* the namespace index
@@ -288,7 +288,7 @@
// type and modcount
int type = in.readInt();
state.setModCount((short) ((type >> 16) & 0x0ffff));
- type&=0x0ffff;
+ type &= 0x0ffff;
state.setType(type);
// multiValued
state.setMultiValued(in.readBoolean());
@@ -350,9 +350,9 @@
// Strings are serialized as <length><byte[]>
int len = in.readInt();
byte[] bytes = new byte[len];
- int pos=0;
+ int pos = 0;
while (pos < len) {
- pos+= in.read(bytes, pos, len-pos);
+ pos += in.read(bytes, pos, len - pos);
}
val = InternalValue.valueOf(new String(bytes, "UTF-8"), type);
}
@@ -384,7 +384,7 @@
switch (state.getType()) {
case PropertyType.BINARY:
try {
- if(InternalValue.USE_DATA_STORE) {
+ if (InternalValue.USE_DATA_STORE && dataStore != null) {
out.writeInt(-2);
out.writeUTF(val.toString());
break;
@@ -424,7 +424,7 @@
try {
int pos = 0;
while (pos < size) {
- int n = in.read(data, pos, (int) size-pos);
+ int n = in.read(data, pos, (int) size - pos);
if (n < 0) {
throw new EOFException();
}
@@ -483,9 +483,9 @@
public UUID readUUID(DataInputStream in) throws IOException {
if (in.readBoolean()) {
byte[] bytes = new byte[16];
- int pos=0;
+ int pos = 0;
while (pos < 16) {
- pos += in.read(bytes, pos, 16-pos);
+ pos += in.read(bytes, pos, 16 - pos);
}
return new UUID(bytes);
} else {
@@ -517,9 +517,9 @@
public NodeId readID(DataInputStream in) throws IOException {
if (in.readBoolean()) {
byte[] bytes = new byte[16];
- int pos=0;
+ int pos = 0;
while (pos < 16) {
- pos += in.read(bytes, pos, 16-pos);
+ pos += in.read(bytes, pos, 16 - pos);
}
return new NodeId(new UUID(bytes));
} else {
@@ -608,7 +608,7 @@
*/
public QName readIndexedQName(DataInputStream in) throws IOException {
int index = in.readInt();
- if (index<0) {
+ if (index < 0) {
return null;
} else {
String uri = nsIndex.indexToString(index);
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInResource.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInResource.java?rev=573209&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInResource.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInResource.java Thu Sep 6 03:07:41 2007
@@ -0,0 +1,154 @@
+/*
+ * 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.jackrabbit.core.value;
+
+import org.apache.jackrabbit.core.fs.FileSystemException;
+import org.apache.jackrabbit.core.fs.FileSystemResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.jcr.RepositoryException;
+
+/**
+ * Represents binary data which is stored in a file system resource.
+ */
+public class BLOBInResource extends BLOBFileValue {
+
+ /**
+ * The default logger
+ */
+ private static final Logger LOG = LoggerFactory.getLogger(BLOBInResource.class);
+
+ /**
+ * the prefix of the string representation of this value
+ */
+ private static final String PREFIX = "fsResource:";
+
+ /**
+ * underlying file system resource
+ */
+ private final FileSystemResource fsResource;
+
+ /**
+ * the file length
+ */
+ private final long length;
+
+ /**
+ * Creates a new instance from a stream.
+ *
+ * @param in the input stream
+ * @throws IOException
+ */
+ private BLOBInResource(FileSystemResource fsResource) throws IOException {
+ try {
+ if (!fsResource.exists()) {
+ throw new IOException(fsResource.getPath()
+ + ": the specified resource does not exist");
+ }
+ length = fsResource.length();
+ } catch (FileSystemException fse) {
+ throw new IOException(fsResource.getPath()
+ + ": Error while creating value: " + fse.toString());
+ }
+ this.fsResource = fsResource;
+ }
+
+ /**
+ * Creates a new instance from a file system resource.
+ *
+ * @param fsResource the resource
+ */
+ static BLOBInResource getInstance(FileSystemResource fsResource) throws IOException {
+ return new BLOBInResource(fsResource);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void delete(boolean pruneEmptyParentDirs) {
+ try {
+ fsResource.delete(pruneEmptyParentDirs);
+ } catch (FileSystemException fse) {
+ // ignore
+ LOG.warn("Error while deleting BLOBFileValue: " + fse.getMessage());
+ }
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void discard() {
+ // this instance is not backed by temporarily allocated resource/buffer
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getLength() {
+ return length;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public InputStream getStream() throws IllegalStateException, RepositoryException {
+ try {
+ return fsResource.getInputStream();
+ } catch (FileSystemException fse) {
+ throw new RepositoryException(fsResource.getPath()
+ + ": the specified resource does not exist", fse);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString() {
+ return PREFIX + fsResource.toString();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof BLOBInResource) {
+ BLOBInResource other = (BLOBInResource) obj;
+ return length == other.length && fsResource.equals(other.fsResource);
+ }
+ return false;
+ }
+
+ /**
+ * Returns zero to satisfy the Object equals/hashCode contract.
+ * This class is mutable and not meant to be used as a hash key.
+ *
+ * @return always zero
+ * @see Object#hashCode()
+ */
+ public int hashCode() {
+ return 0;
+ }
+
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInResource.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInTempFile.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInTempFile.java?rev=573209&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInTempFile.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInTempFile.java Thu Sep 6 03:07:41 2007
@@ -0,0 +1,172 @@
+/*
+ * 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.jackrabbit.core.value;
+
+import org.apache.jackrabbit.util.TransientFileFactory;
+
+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.OutputStream;
+
+import javax.jcr.RepositoryException;
+
+/**
+ * Represents binary data which is stored in a temporary file.
+ */
+public class BLOBInTempFile extends BLOBFileValue {
+
+ /**
+ * the prefix of the string representation of this value
+ */
+ private static final String PREFIX = "file:";
+
+ private File file;
+ private long length;
+ private final boolean temp;
+
+ /**
+ * Creates a new instance from a stream.
+ *
+ * @param in the input stream
+ * @throws IOException
+ */
+ private BLOBInTempFile(InputStream in, boolean temp) throws IOException {
+ this.temp = temp;
+ OutputStream out = null;
+ try {
+ TransientFileFactory fileFactory = TransientFileFactory.getInstance();
+ file = fileFactory.createTransientFile("bin", null, null);
+ out = new FileOutputStream(file);
+ byte[] buffer = new byte[4 * 1024];
+ while (true) {
+ int len = in.read(buffer);
+ if (len < 0) {
+ break;
+ }
+ out.write(buffer, 0, len);
+ length += len;
+ }
+ } finally {
+ if (out != null) {
+ out.close();
+ }
+ in.close();
+ }
+ }
+
+ /**
+ * Creates a new instance from file.
+ *
+ * @param in the input stream
+ */
+ private BLOBInTempFile(File file, boolean temp) {
+ this.file = file;
+ this.length = file.length();
+ this.temp = temp;
+ }
+
+ /**
+ * Creates a new instance from a stream.
+ *
+ * @param in the stream
+ */
+ static BLOBInTempFile getInstance(InputStream in, boolean temp) throws IOException {
+ return new BLOBInTempFile(in, temp);
+ }
+
+ /**
+ * Creates a new instance from a file.
+ *
+ * @param file the file
+ */
+ static BLOBInTempFile getInstance(File file, boolean temp) throws IOException {
+ return new BLOBInTempFile(file, temp);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void delete(boolean pruneEmptyParentDirs) {
+ file.delete();
+ length = -1;
+ file = null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void discard() {
+ if (temp) {
+ delete(true);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getLength() {
+ return length;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public InputStream getStream() throws IllegalStateException, RepositoryException {
+ try {
+ return new FileInputStream(file);
+ } catch (FileNotFoundException fnfe) {
+ throw new RepositoryException("file backing binary value not found", fnfe);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString() {
+ return PREFIX + file.toString();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof BLOBInTempFile) {
+ BLOBInTempFile other = (BLOBInTempFile) obj;
+ return (file == other.file) || (length == other.length && file != null && file.equals(other.file));
+ }
+ return false;
+ }
+
+ /**
+ * Returns zero to satisfy the Object equals/hashCode contract.
+ * This class is mutable and not meant to be used as a hash key.
+ *
+ * @return always zero
+ * @see Object#hashCode()
+ */
+ public int hashCode() {
+ return 0;
+ }
+
+}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/InternalValue.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/InternalValue.java?rev=573209&r1=573208&r2=573209&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/InternalValue.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/InternalValue.java Thu Sep 6 03:07:41 2007
@@ -122,11 +122,7 @@
case PropertyType.BINARY:
try {
if (USE_DATA_STORE) {
- if (store == null) {
- return new InternalValue(BLOBInTempFile.getInstance(value.getStream()));
- } else {
- return new InternalValue(getBLOBFileValue(store, value.getStream()));
- }
+ return new InternalValue(getBLOBFileValue(store, value.getStream()));
}
if (value instanceof BLOBFileValue) {
return new InternalValue((BLOBFileValue) value);
@@ -169,7 +165,6 @@
}
case PropertyType.STRING:
return create(value.getString());
-
default:
throw new IllegalArgumentException("illegal value");
}
@@ -235,17 +230,18 @@
*/
public static InternalValue createTemporary(InputStream value) throws IOException {
if (USE_DATA_STORE) {
- return new InternalValue(BLOBInTempFile.getInstance(value));
+ return new InternalValue(getBLOBFileValue(null, value));
}
return new InternalValue(new BLOBValue(value, true));
}
/**
- * Create an internal value that is backed by a temporary file (if data store usage is disabled)
- * or (if it is enabled) in the data store.
+ * Create an internal value that is backed by a temporary file
+ * (if data store usage is disabled or the store is null)
+ * or in the data store if it is not null and enabled.
*
* @param value the stream
- * @param store the data store
+ * @param store the data store or null to use a temporary file
* @return the internal value
*/
public static InternalValue createTemporary(InputStream value, DataStore store) throws IOException {
@@ -262,6 +258,9 @@
* @throws IOException
*/
public static InternalValue create(InputStream value) throws IOException {
+ if (USE_DATA_STORE) {
+ return new InternalValue(getBLOBFileValue(null, value));
+ }
return new InternalValue(new BLOBValue(value, false));
}
@@ -270,8 +269,10 @@
* @return
* @throws IOException
*/
- public static InternalValue create(FileSystemResource value)
- throws IOException {
+ public static InternalValue create(FileSystemResource value) throws IOException {
+ if (USE_DATA_STORE) {
+ return new InternalValue(BLOBInResource.getInstance(value));
+ }
return new InternalValue(new BLOBValue(value));
}
@@ -281,6 +282,9 @@
* @throws IOException
*/
public static InternalValue create(File value) throws IOException {
+ if (USE_DATA_STORE) {
+ return new InternalValue(BLOBInTempFile.getInstance(value, false));
+ }
return new InternalValue(new BLOBValue(value));
}
@@ -292,7 +296,7 @@
* @return the value
*/
public static InternalValue create(DataStore store, String id) {
- assert USE_DATA_STORE;
+ assert USE_DATA_STORE && store != null;
return new InternalValue(getBLOBFileValue(store, id));
}
@@ -613,7 +617,11 @@
} else {
// a few bytes are already read, need to re-build the input stream
in = new SequenceInputStream(new ByteArrayInputStream(buffer, 0, pos), in);
- return BLOBInDataStore.getInstance(store, in);
+ if (store != null) {
+ return BLOBInDataStore.getInstance(store, in);
+ } else {
+ return BLOBInTempFile.getInstance(in, true);
+ }
}
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/BufferedStringValue.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/BufferedStringValue.java?rev=573209&r1=573208&r2=573209&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/BufferedStringValue.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/BufferedStringValue.java Thu Sep 6 03:07:41 2007
@@ -34,6 +34,7 @@
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
+import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringReader;
@@ -285,6 +286,10 @@
} else {
// >= 65kb: deserialize BINARY type
// using Reader and temporay file
+ if (InternalValue.USE_DATA_STORE) {
+ Base64ReaderInputStream in = new Base64ReaderInputStream(reader());
+ return InternalValue.createTemporary(in);
+ }
TransientFileFactory fileFactory = TransientFileFactory.getInstance();
File tmpFile = fileFactory.createTransientFile("bin", null, null);
FileOutputStream out = new FileOutputStream(tmpFile);
@@ -305,6 +310,47 @@
}
} catch (IOException e) {
throw new RepositoryException("Error accessing property value", e);
+ }
+ }
+
+ private static class Base64ReaderInputStream extends InputStream {
+
+ private static final int BUFFER_SIZE = 1024;
+ private final char[] chars;
+ private final ByteArrayOutputStream out;
+ private final Reader reader;
+ private int pos;
+ private int remaining;
+ private byte[] buffer;
+
+ public Base64ReaderInputStream(Reader reader) {
+ chars = new char[BUFFER_SIZE];
+ this.reader = reader;
+ out = new ByteArrayOutputStream(BUFFER_SIZE);
+ }
+
+ private void fillBuffer() throws IOException {
+ int len = reader.read(chars, 0, BUFFER_SIZE);
+ if (len < 0) {
+ remaining = -1;
+ return;
+ }
+ Base64.decode(chars, 0, len, out);
+ buffer = out.toByteArray();
+ pos = 0;
+ remaining = buffer.length;
+ out.reset();
+ }
+
+ public int read() throws IOException {
+ if (remaining == 0) {
+ fillBuffer();
+ }
+ if (remaining < 0) {
+ return -1;
+ }
+ remaining--;
+ return buffer[pos++] & 0xff;
}
}