| /* |
| * 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.jclouds.jdbc.strategy; |
| |
| import java.io.IOException; |
| import java.sql.SQLException; |
| import java.util.Collection; |
| import java.util.List; |
| |
| import javax.inject.Inject; |
| import javax.inject.Provider; |
| import javax.persistence.PersistenceException; |
| |
| import org.jclouds.blobstore.LocalStorageStrategy; |
| import org.jclouds.blobstore.domain.Blob; |
| import org.jclouds.blobstore.domain.BlobAccess; |
| import org.jclouds.blobstore.domain.BlobBuilder; |
| import org.jclouds.blobstore.domain.ContainerAccess; |
| import org.jclouds.blobstore.domain.MutableStorageMetadata; |
| import org.jclouds.blobstore.domain.StorageMetadata; |
| import org.jclouds.blobstore.domain.StorageType; |
| import org.jclouds.blobstore.domain.internal.MutableStorageMetadataImpl; |
| import org.jclouds.blobstore.options.CreateContainerOptions; |
| import org.jclouds.blobstore.options.ListContainerOptions; |
| import org.jclouds.domain.Location; |
| import org.jclouds.domain.LocationBuilder; |
| import org.jclouds.domain.LocationScope; |
| import org.jclouds.io.ContentMetadata; |
| import org.jclouds.jdbc.conversion.BlobEntityToBlob; |
| import org.jclouds.jdbc.entity.BlobEntity; |
| import org.jclouds.jdbc.entity.ContainerEntity; |
| import org.jclouds.jdbc.predicates.validators.JdbcBlobKeyValidator; |
| import org.jclouds.jdbc.predicates.validators.JdbcContainerNameValidator; |
| import org.jclouds.jdbc.service.JdbcService; |
| |
| import com.google.common.base.Preconditions; |
| import com.google.common.collect.ImmutableList; |
| |
| /** |
| * JdbcStorageStrategy implements a blob store that stores objects |
| * on a jdbc supported database. Content metadata and user attributes are stored in |
| * the database as well. |
| */ |
| public class JdbcStorageStrategy implements LocalStorageStrategy { |
| |
| private final Provider<BlobBuilder> blobBuilders; |
| private final JdbcService jdbcService; |
| private final JdbcContainerNameValidator jdbcContainerNameValidator; |
| private final JdbcBlobKeyValidator jdbcBlobKeyValidator; |
| private final BlobEntityToBlob blobEntityToBlob; |
| private final Location mockLocation; |
| |
| @Inject |
| JdbcStorageStrategy(Provider<BlobBuilder> blobBuilders, |
| JdbcContainerNameValidator jdbcContainerNameValidator, JdbcBlobKeyValidator jdbcBlobKeyValidator, |
| JdbcService jdbcService, BlobEntityToBlob blobEntityToBlob) |
| throws ClassNotFoundException, IllegalAccessException, InstantiationException, SQLException { |
| this.jdbcService = jdbcService; |
| this.blobBuilders = blobBuilders; |
| this.jdbcContainerNameValidator = jdbcContainerNameValidator; |
| this.jdbcBlobKeyValidator = jdbcBlobKeyValidator; |
| this.blobEntityToBlob = blobEntityToBlob; |
| this.mockLocation = new LocationBuilder() |
| .id("jdbc") |
| .scope(LocationScope.PROVIDER) |
| .description("http://localhost/transient") |
| .build(); |
| } |
| |
| /** |
| * Checks if a container exists |
| * |
| * @param container the name of the container to check |
| * @return true if the container exists, false otherwise |
| */ |
| @Override |
| public boolean containerExists(String container) { |
| jdbcContainerNameValidator.validate(container); |
| return jdbcService.findContainerByName(container) != null; |
| } |
| |
| /** |
| * Lists all the container names |
| * |
| * @return an iterable with the container names |
| */ |
| @Override |
| public Collection<String> getAllContainerNames() { |
| List<ContainerEntity> containerEntities = jdbcService.findAllContainers(); |
| ImmutableList.Builder<String> result = ImmutableList.builder(); |
| for (ContainerEntity c : containerEntities) { |
| result.add(c.getName()); |
| } |
| return result.build(); |
| } |
| |
| /** |
| * Creates a container. The location is ignored. |
| * |
| * @param container the name of the container to create |
| * @param createContainerOptions creation options to the container. defaults the ContainerAccess |
| * to ContainerAccess.PRIVATE |
| * @return true if the container was created, false otherwise |
| */ |
| @Override |
| public boolean createContainerInLocation(String container, Location location, |
| CreateContainerOptions createContainerOptions) { |
| jdbcContainerNameValidator.validate(container); |
| |
| ContainerAccess containerAccess = createContainerOptions == null ? ContainerAccess.PRIVATE |
| : (createContainerOptions.isPublicRead() ? ContainerAccess.PUBLIC_READ |
| : ContainerAccess.PRIVATE); |
| try { |
| jdbcService.createContainer(container, containerAccess); |
| } catch (PersistenceException e) { |
| return false; |
| } catch (IllegalArgumentException e) { |
| return false; |
| } |
| return true; |
| } |
| |
| /** |
| * Gets the container accessibility |
| * |
| * @param container the name of the container |
| * @return a value with the container's accessibility |
| */ |
| @Override |
| public ContainerAccess getContainerAccess(String container) { |
| return jdbcService.findContainerByName(container).getContainerAccess(); |
| } |
| |
| /** |
| * Sets the container accessibility |
| * |
| * @param container the name of the container |
| * @param containerAccess the new container access for the container |
| */ |
| @Override |
| public void setContainerAccess(String container, ContainerAccess containerAccess) { |
| jdbcService.setContainerAccessByName(container, containerAccess); |
| } |
| |
| /** |
| * Deletes a container and all the blobs in it |
| * |
| * @param container the name of the container to delete |
| */ |
| @Override |
| public void deleteContainer(String container) { |
| jdbcContainerNameValidator.validate(container); |
| jdbcService.deleteBlobsByContainer(container); |
| jdbcService.deleteContainerByName(container); |
| } |
| |
| /** |
| * Deletes all the blobs in a container |
| * |
| * @param container the name of the container to clear |
| */ |
| @Override |
| public void clearContainer(String container) { |
| jdbcService.deleteBlobsByContainer(container); |
| } |
| |
| /** |
| * Deletes all the blobs in a container |
| * |
| * @param container the name of the container to clear |
| * @param options options to filter what blobs are cleared |
| */ |
| @Override |
| public void clearContainer(String container, ListContainerOptions options) { |
| Preconditions.checkArgument(options.getPrefix() == null, "prefix not yet implemented"); |
| if (options.getDir() != null) { |
| jdbcService.deleteBlobsByDirectory(container, options.getDir(), true); |
| } |
| else { |
| clearContainer(container); |
| } |
| } |
| |
| /** |
| * Gets a container's metadata |
| * |
| * @param containerName the name of the container |
| * @return the container's metadata |
| */ |
| @Override |
| public StorageMetadata getContainerMetadata(String containerName) { |
| ContainerEntity containerEntity = jdbcService.findContainerByName(containerName); |
| MutableStorageMetadata metadata = null; |
| if (containerEntity != null) { |
| metadata = new MutableStorageMetadataImpl(); |
| metadata.setName(containerName); |
| metadata.setType(StorageType.CONTAINER); |
| metadata.setLocation(mockLocation); |
| metadata.setCreationDate(containerEntity.getCreationDate()); |
| } |
| return metadata; |
| } |
| |
| /** |
| * Checks if a blob exists |
| * |
| * @param container the name of the container containing the blob |
| * @param key the blob's key |
| * @return true if the blob exists in the container, false otherwise |
| */ |
| @Override |
| public boolean blobExists(String container, String key) { |
| jdbcContainerNameValidator.validate(container); |
| jdbcBlobKeyValidator.validate(key); |
| return jdbcService.blobExists(container, key); |
| } |
| |
| /** |
| * Lists all the blob keys in a container |
| * |
| * @param container the name of the container |
| * @return the blob keys inside the container |
| */ |
| @Override |
| public Iterable<String> getBlobKeysInsideContainer(String container, String prefix) throws IOException { |
| List<BlobEntity> blobEntities = jdbcService.findBlobsByContainer(container); |
| ImmutableList.Builder<String> result = ImmutableList.builder(); |
| for (BlobEntity blobEntity : blobEntities) { |
| if (prefix != null && !blobEntity.getKey().startsWith(prefix)) { |
| continue; |
| } |
| result.add(blobEntity.getKey()); |
| } |
| return result.build(); |
| } |
| |
| /** |
| * Gets a blob in a container |
| * |
| * @param container the name of the container containing the blob |
| * @param key the key of the blob to get |
| * @return the blob in the container or null if the blob does not exist |
| */ |
| @Override |
| public Blob getBlob(String container, String key) { |
| return blobEntityToBlob.apply(jdbcService.findBlobById(container, key)); |
| } |
| |
| /** |
| * Store a blob in a container |
| * |
| * @param container the name of the container |
| * @param blob the blob to store |
| * @return the blob's etag |
| */ |
| @Override |
| public String putBlob(String container, Blob blob) throws IOException { |
| String key = blob.getMetadata().getName(); |
| jdbcContainerNameValidator.validate(container); |
| jdbcBlobKeyValidator.validate(key); |
| return jdbcService.createOrModifyBlob(container, blob).getEtag(); |
| } |
| |
| /** |
| * Removes a blob from a container |
| * |
| * @param container the name of the container containing the blob |
| * @param key the blob's key |
| */ |
| @Override |
| public void removeBlob(String container, String key) { |
| jdbcService.deleteBlob(container, key); |
| } |
| |
| /** |
| * Gets the blob accessibility |
| * |
| * @param container the name of the container containing the blob |
| * @param key the blob's key |
| * @return a value with the container's accessibility |
| */ |
| @Override |
| public BlobAccess getBlobAccess(String container, String key) { |
| return jdbcService.findBlobById(container, key).getBlobAccess(); |
| } |
| |
| /** |
| * Sets the blob accessibility |
| * |
| * @param container the name of the container containing the blob |
| * @param key the blob's key |
| * @param blobAccess the new blob access for the blob |
| */ |
| @Override |
| public void setBlobAccess(String container, String key, BlobAccess blobAccess) { |
| jdbcService.setBlobAccessById(container, key, blobAccess); |
| } |
| |
| /** |
| * Gets the container location |
| * |
| * @return always return null |
| */ |
| @Override |
| public Location getLocation(String container) { |
| return mockLocation; |
| } |
| |
| /** |
| * Gets the separator used for directory naming |
| * |
| * @return a string containing "/" |
| */ |
| @Override |
| public String getSeparator() { |
| return "/"; |
| } |
| |
| /** |
| * Count the blobs in a container |
| * |
| * @param container the name of the container |
| * @param options options to filter what blobs are counted |
| * @return the number of blobs in the container |
| */ |
| public long countBlobs(String container, ListContainerOptions options) { |
| return options.getDir() == null ? jdbcService.findBlobsByContainer(container).size() |
| : jdbcService.findBlobsByDirectory(container, options.getDir(), options.isRecursive()).size(); |
| } |
| |
| /** |
| * Checks if a directory exists |
| * |
| * @param container the name of the container |
| * @param directory the name of the directory |
| * @return true if the directory exists, false otherwise |
| */ |
| public boolean directoryExists(String container, String directory) { |
| Blob blob = getBlob(container, directory); |
| return blob != null && "application/directory".equals( |
| blob.getMetadata().getContentMetadata().getContentType()); |
| } |
| |
| /** |
| * Store a blob in a directory |
| * |
| * @param container the name of the container |
| * @param blob the blob to store |
| * @return the blob's etag |
| */ |
| private String putDirectoryBlob(final String container, final Blob blob) { |
| String blobKey = blob.getMetadata().getName(); |
| ContentMetadata metadata = blob.getMetadata().getContentMetadata(); |
| Long contentLength = metadata.getContentLength(); |
| if (contentLength != null && contentLength != 0) { |
| throw new IllegalArgumentException( |
| "Directory blob cannot have content: " + blobKey); |
| } |
| return jdbcService.createDirectoryBlob(container, blob).getEtag(); |
| } |
| |
| /** |
| * Creates a new directory |
| * |
| * @param container the name of the container |
| * @param directory the name of the directory to create |
| */ |
| public void createDirectory(String container, String directory) { |
| Blob blob = blobBuilders.get().name(directory).payload("").build(); |
| blob.getMetadata().getContentMetadata().setContentType("application/directory"); |
| putDirectoryBlob(container, blob); |
| } |
| |
| /** |
| * Delete an existing directory |
| * |
| * @param container the name of the container |
| * @param directory the name of the directory to delete |
| */ |
| public void deleteDirectory(String container, String directory) { |
| BlobEntity entity = jdbcService.findBlobById(container, directory); |
| if (entity != null && entity.isDirectory()) { |
| jdbcService.deleteBlob(container, directory); |
| } |
| } |
| |
| } |