Java tutorial
/* * 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.service; import com.google.common.collect.ImmutableList; import com.google.common.hash.HashCode; import com.google.common.hash.Hashing; import com.google.common.hash.HashingInputStream; import com.google.common.io.ByteStreams; import com.google.inject.Inject; import com.google.inject.Singleton; import com.google.inject.persist.Transactional; import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.BlobAccess; import org.jclouds.blobstore.domain.ContainerAccess; import org.jclouds.jdbc.conversion.BlobToBlobEntity; import org.jclouds.jdbc.entity.BlobEntity; import org.jclouds.jdbc.entity.BlobEntityPK; import org.jclouds.jdbc.entity.ChunkEntity; import org.jclouds.jdbc.entity.ContainerEntity; import org.jclouds.jdbc.entity.PayloadEntity; import org.jclouds.jdbc.reference.JdbcConstants; import org.jclouds.jdbc.repository.BlobRepository; import org.jclouds.jdbc.repository.ChunkRepository; import org.jclouds.jdbc.repository.ContainerRepository; import org.jclouds.util.Closeables2; import java.io.IOException; import java.io.InputStream; import java.util.Arrays; import java.util.Date; import java.util.List; import static com.google.common.io.BaseEncoding.base16; @Singleton public class JdbcService { private static final String DIRECTORY_MD5 = Hashing.md5().hashBytes(new byte[0]).toString(); private final ContainerRepository containerRepository; private final BlobRepository blobRepository; private final ChunkRepository chunkRepository; private final BlobToBlobEntity blobToBlobEntity; @Inject JdbcService(ContainerRepository containerRepository, BlobRepository blobRepository, ChunkRepository chunkRepository, BlobToBlobEntity blobToBlobEntity) { this.containerRepository = containerRepository; this.blobRepository = blobRepository; this.chunkRepository = chunkRepository; this.blobToBlobEntity = blobToBlobEntity; } @Transactional public void createContainer(String containerName, ContainerAccess access) { containerRepository.create(ContainerEntity.builder().name(containerName).containerAccess(access).build()); } @Transactional public void createContainer(String containerName) { createContainer(containerName, null); } @Transactional public List<ContainerEntity> findAllContainers() { return containerRepository.findAllContainers(); } @Transactional public ContainerEntity findContainerByName(String containerName) { return containerRepository.findContainerByName(containerName); } @Transactional public void deleteContainerByName(String containerName) { containerRepository.deleteContainerByName(containerName); } @Transactional public void setContainerAccessByName(String containerName, ContainerAccess access) { ContainerEntity containerEntity = containerRepository.findContainerByName(containerName); containerEntity.setContainerAccess(access); containerRepository.save(containerEntity); } @Transactional public boolean blobExists(String containerName, String key) { return findBlobById(containerName, key) != null; } @Transactional(rollbackOn = IOException.class) public BlobEntity createOrModifyBlob(String containerName, Blob blob, BlobAccess blobAccess) throws IOException { List<Long> chunks; HashingInputStream his = new HashingInputStream(Hashing.md5(), blob.getPayload().openStream()); try { chunks = storeData(his); } finally { Closeables2.closeQuietly(his); } HashCode actualHashCode = his.hash(); HashCode expectedHashCode = blob.getPayload().getContentMetadata().getContentMD5AsHashCode(); if (expectedHashCode != null && !actualHashCode.equals(expectedHashCode)) { throw new IOException( "MD5 hash code mismatch, actual: " + actualHashCode + " expected: " + expectedHashCode); } String key = blob.getMetadata().getName(); Date creationDate = null; BlobEntity oldBlobEntity = findBlobById(containerName, key); if (oldBlobEntity != null) { creationDate = oldBlobEntity.getCreationDate(); } BlobEntity blobEntity = blobToBlobEntity.apply(blob); blobEntity.getPayload().setChunks(chunks); blobEntity.setContainerEntity(containerRepository.findContainerByName(containerName)); blobEntity.setKey(key); blobEntity.setBlobAccess(blobAccess); blobEntity.setTier(blob.getMetadata().getTier()); blobEntity.setCreationDate(creationDate); blobEntity.setLastModified(new Date()); blobEntity.setEtag(base16().lowerCase().encode(actualHashCode.asBytes())); blobEntity.getPayload().setContentMD5(actualHashCode.asBytes()); BlobEntity result = blobRepository.save(blobEntity); return result; } @Transactional public BlobEntity createDirectoryBlob(String containerName, Blob blob, BlobAccess blobAccess) { BlobEntity blobEntity = BlobEntity.builder(null, null).userMetadata(blob.getMetadata().getUserMetadata()) .directory(true).payload(PayloadEntity.builder().contentType("application/directory").build()) .build(); blobEntity.setContainerEntity(containerRepository.findContainerByName(containerName)); blobEntity.setKey(blob.getMetadata().getName()); blobEntity.setBlobAccess(blobAccess); blobEntity.setEtag(DIRECTORY_MD5); return blobRepository.save(blobEntity); } @Transactional public BlobEntity createDirectoryBlob(String containerName, Blob blob) { return createDirectoryBlob(containerName, blob, null); } @Transactional(rollbackOn = IOException.class) public BlobEntity createOrModifyBlob(String containerName, Blob blob) throws IOException { return createOrModifyBlob(containerName, blob, null); } @Transactional public BlobEntity findBlobById(String containerName, String key) { ContainerEntity containerEntity = containerRepository.findContainerByName(containerName); return containerEntity == null ? null : blobRepository.find(new BlobEntityPK(containerEntity.getId(), key)); } @Transactional public ChunkEntity findChunkById(Long id) { return chunkRepository.find(id); } @Transactional public List<BlobEntity> findBlobsByContainer(String containerName) { return blobRepository.findBlobsByContainer(containerRepository.findContainerByName(containerName)); } @Transactional public List<BlobEntity> findBlobsByDirectory(String containerName, String directoryName, boolean recursive) { ImmutableList.Builder<BlobEntity> result = ImmutableList.builder(); List<BlobEntity> blobEntities = blobRepository .findBlobsByDirectory(containerRepository.findContainerByName(containerName), directoryName); result.addAll(blobEntities); if (recursive) { for (BlobEntity blobEntity : blobEntities) { if (blobEntity.isDirectory()) { result.addAll(findBlobsByDirectory(containerName, blobEntity.getKey(), true)); } } } return result.build(); } @Transactional public void deleteBlobsByContainer(String containerName) { List<BlobEntity> blobs = findBlobsByContainer(containerName); for (BlobEntity blob : blobs) { deleteBlob(containerName, blob.getKey()); } } @Transactional public void deleteBlobsByDirectory(String containerName, String directoryName, boolean recursive) { List<BlobEntity> blobs = findBlobsByDirectory(containerName, directoryName, false); for (BlobEntity blob : blobs) { if (!blob.isDirectory()) { deleteBlob(containerName, blob.getKey()); } else { if (recursive) { deleteBlobsByDirectory(containerName, blob.getKey(), true); deleteBlob(containerName, blob.getKey()); } } } } @Transactional public void deleteBlob(String containerName, String key) { BlobEntity blobEntity = findBlobById(containerName, key); if (blobEntity != null) { deleteChunks(blobEntity.getPayload().getChunks()); blobRepository.delete(blobEntity); } } @Transactional public void setBlobAccessById(String containerName, String key, BlobAccess access) { BlobEntity blobEntity = findBlobById(containerName, key); blobEntity.setBlobAccess(access); blobRepository.save(blobEntity); } @Transactional private void deleteChunks(List<Long> chunkIds) { for (Long chunkId : chunkIds) { chunkRepository.delete(chunkRepository.find(chunkId)); } } @Transactional(rollbackOn = IOException.class) private List<Long> storeData(InputStream data) throws IOException { ImmutableList.Builder<Long> chunks = ImmutableList.builder(); while (true) { byte[] buffer = new byte[JdbcConstants.DEFAULT_CHUNK_SIZE]; int bytes = ByteStreams.read(data, buffer, 0, JdbcConstants.DEFAULT_CHUNK_SIZE); if (bytes == 0) { break; } else if (bytes != buffer.length) { buffer = Arrays.copyOf(buffer, bytes); } chunks.add(chunkRepository.create(new ChunkEntity(buffer, bytes)).getId()); } return chunks.build(); } }