diff --git a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/PCSBlobStore.java b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/PCSBlobStore.java new file mode 100644 index 0000000000..cae8dc09bc --- /dev/null +++ b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/PCSBlobStore.java @@ -0,0 +1,162 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2; + +import java.util.List; +import java.util.concurrent.Future; + +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; + +import org.jclouds.blobstore.BlobStore; +import org.jclouds.blobstore.functions.ReturnTrueOnNotFoundOr404; +import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404; +import org.jclouds.http.filters.BasicAuthentication; +import org.jclouds.http.options.GetOptions; +import org.jclouds.mezeo.pcs2.binders.CreateContainerBinder; +import org.jclouds.mezeo.pcs2.binders.PCSFileAsMultipartFormBinder; +import org.jclouds.mezeo.pcs2.domain.ContainerMetadata; +import org.jclouds.mezeo.pcs2.domain.FileMetadata; +import org.jclouds.mezeo.pcs2.domain.PCSFile; +import org.jclouds.mezeo.pcs2.endpoints.RootContainer; +import org.jclouds.mezeo.pcs2.functions.AddMetadataAndParseResourceIdIntoBytes; +import org.jclouds.mezeo.pcs2.functions.AssembleBlobFromContentAndMetadataCache; +import org.jclouds.mezeo.pcs2.functions.ContainerAndFileNameToResourceId; +import org.jclouds.mezeo.pcs2.functions.ContainerNameToResourceId; +import org.jclouds.mezeo.pcs2.functions.InvalidateContainerNameCacheAndReturnTrueIf2xx; +import org.jclouds.mezeo.pcs2.functions.InvalidatePCSKeyCacheAndReturnTrueIf2xx; +import org.jclouds.mezeo.pcs2.functions.ReturnFalseIfContainerNotFound; +import org.jclouds.mezeo.pcs2.functions.ReturnTrueIfContainerAlreadyExists; +import org.jclouds.mezeo.pcs2.functions.ReturnTrueIfContainerNotFound; +import org.jclouds.mezeo.pcs2.xml.FileListToContainerMetadataListHandler; +import org.jclouds.mezeo.pcs2.xml.FileListToFileMetadataListHandler; +import org.jclouds.mezeo.pcs2.xml.FileMetadataHandler; +import org.jclouds.rest.Endpoint; +import org.jclouds.rest.EntityParam; +import org.jclouds.rest.ExceptionParser; +import org.jclouds.rest.Headers; +import org.jclouds.rest.ParamParser; +import org.jclouds.rest.RequestFilters; +import org.jclouds.rest.ResponseParser; +import org.jclouds.rest.SkipEncoding; +import org.jclouds.rest.XMLResponseParser; + +/** + * Provides access to Mezeo PCS v2 via their REST API. + *

+ * + * @see + * @author Adrian Cole + */ +@SkipEncoding('/') +@RequestFilters(BasicAuthentication.class) +public interface PCSBlobStore extends BlobStore { + + @GET + @XMLResponseParser(FileListToContainerMetadataListHandler.class) + @Headers(keys = "X-Cloud-Depth", values = "2") + @Path("/contents") + @Endpoint(RootContainer.class) + List listContainers(); + + @GET + @ExceptionParser(ReturnFalseIfContainerNotFound.class) + @Path("/containers/{containerResourceId}") + @Endpoint(PCS.class) + boolean containerExists( + @PathParam("containerResourceId") @ParamParser(ContainerNameToResourceId.class) String containerName); + + @POST + @Path("/contents") + @Endpoint(RootContainer.class) + @ExceptionParser(ReturnTrueIfContainerAlreadyExists.class) + Future createContainer(@EntityParam(CreateContainerBinder.class) String container); + + @DELETE + @ExceptionParser(ReturnTrueIfContainerNotFound.class) + @Path("/containers/{containerResourceId}") + @Endpoint(PCS.class) + @ResponseParser(InvalidateContainerNameCacheAndReturnTrueIf2xx.class) + Future deleteContainer( + @PathParam("containerResourceId") @ParamParser(ContainerNameToResourceId.class) String containerName); + + @GET + @XMLResponseParser(FileListToFileMetadataListHandler.class) + @Headers(keys = "X-Cloud-Depth", values = "2") + @Path("/containers/{containerResourceId}/contents") + @Endpoint(PCS.class) + Future> listBlobs( + @PathParam("containerResourceId") @ParamParser(ContainerNameToResourceId.class) String containerName); + + @POST + @Path("/containers/{containerResourceId}/contents") + @Endpoint(PCS.class) + @ResponseParser(AddMetadataAndParseResourceIdIntoBytes.class) + Future putBlob( + @PathParam("containerResourceId") @ParamParser(ContainerNameToResourceId.class) String containerName, + @EntityParam(PCSFileAsMultipartFormBinder.class) PCSFile object); + + @DELETE + @ExceptionParser(ReturnTrueOnNotFoundOr404.class) + @Path("/files/{resourceId}") + @PathParam("resourceId") + @Endpoint(PCS.class) + @ResponseParser(InvalidatePCSKeyCacheAndReturnTrueIf2xx.class) + @ParamParser(ContainerAndFileNameToResourceId.class) + Future removeBlob(String container, String key); + + @GET + @ExceptionParser(ThrowKeyNotFoundOn404.class) + @Path("/files/{resourceId}/content") + @PathParam("resourceId") + @Endpoint(PCS.class) + @ParamParser(ContainerAndFileNameToResourceId.class) + @ResponseParser(AssembleBlobFromContentAndMetadataCache.class) + Future getBlob(String container, String key); + + @GET + @ExceptionParser(ThrowKeyNotFoundOn404.class) + @Path("/files/{resourceId}/content") + @PathParam("resourceId") + @Endpoint(PCS.class) + @ParamParser(ContainerAndFileNameToResourceId.class) + @ResponseParser(AssembleBlobFromContentAndMetadataCache.class) + Future getBlob(String container, String key, GetOptions options); + + @GET + @ExceptionParser(ThrowKeyNotFoundOn404.class) + @Path("/files/{resourceId}") + @PathParam("resourceId") + @Headers(keys = "X-Cloud-Depth", values = "2") + @Endpoint(PCS.class) + @ParamParser(ContainerAndFileNameToResourceId.class) + @XMLResponseParser(FileMetadataHandler.class) + FileMetadata blobMetadata(String container, String key); + +} diff --git a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/PCSContext.java b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/PCSContext.java new file mode 100644 index 0000000000..07b967a500 --- /dev/null +++ b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/PCSContext.java @@ -0,0 +1,43 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2; + +import org.jclouds.blobstore.BlobStoreContext; +import org.jclouds.cloud.CloudContext; +import org.jclouds.mezeo.pcs2.domain.ContainerMetadata; +import org.jclouds.mezeo.pcs2.domain.FileMetadata; +import org.jclouds.mezeo.pcs2.domain.PCSFile; + +/** + * Represents an authenticated context to PCS. + * + * @see PCSBlobStore + * @see CloudContext + * @author Adrian Cole + * + */ +public interface PCSContext extends + BlobStoreContext { + +} \ No newline at end of file diff --git a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/PCSContextBuilder.java b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/PCSContextBuilder.java index e166f47090..7c2cf8d919 100755 --- a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/PCSContextBuilder.java +++ b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/PCSContextBuilder.java @@ -25,34 +25,136 @@ package org.jclouds.mezeo.pcs2; import static com.google.common.base.Preconditions.checkNotNull; +import java.net.URI; import java.util.List; import java.util.Properties; +import java.util.concurrent.ExecutorService; -import org.jclouds.cloud.CloudContext; -import org.jclouds.cloud.CloudContextBuilder; -import org.jclouds.mezeo.pcs2.config.RestPCSCloudModule; +import org.jclouds.blobstore.BlobStoreContextBuilder; +import org.jclouds.mezeo.pcs2.config.PCSContextModule; +import org.jclouds.mezeo.pcs2.config.RestPCSBlobStoreModule; +import org.jclouds.mezeo.pcs2.domain.ContainerMetadata; +import org.jclouds.mezeo.pcs2.domain.FileMetadata; +import org.jclouds.mezeo.pcs2.domain.PCSFile; import org.jclouds.mezeo.pcs2.reference.PCSConstants; +import com.google.inject.Injector; import com.google.inject.Module; +import com.google.inject.TypeLiteral; /** * * @author Adrian Cole */ -public abstract class PCSContextBuilder> extends CloudContextBuilder { +public class PCSContextBuilder extends + BlobStoreContextBuilder { public PCSContextBuilder(Properties props) { - super(props); + super(new TypeLiteral() { + }, new TypeLiteral() { + }, new TypeLiteral() { + }, new TypeLiteral() { + }, props); + checkNotNull(properties.getProperty(PCSConstants.PROPERTY_PCS2_ENDPOINT)); } - public void authenticate(String id, String secret) { - checkNotNull(properties.getProperty(PCSConstants.PROPERTY_PCS2_ENDPOINT)); + public PCSContextBuilder(URI endpoint, String id, String secret) { + this(addEndpointTo(endpoint, new Properties())); properties.setProperty(PCSConstants.PROPERTY_PCS2_USER, checkNotNull(id, "user")); properties.setProperty(PCSConstants.PROPERTY_PCS2_PASSWORD, checkNotNull(secret, "key")); } - protected void addApiModule(List modules) { - modules.add(new RestPCSCloudModule()); + private static Properties addEndpointTo(URI endpoint, Properties properties) { + properties.setProperty(PCSConstants.PROPERTY_PCS2_ENDPOINT, + checkNotNull(endpoint, "endpoint").toString()); + return properties; } + protected void addConnectionModule(List modules) { + modules.add(new RestPCSBlobStoreModule()); + } + + @Override + protected void addContextModule(List modules) { + modules.add(new PCSContextModule()); + } + + @Override + public PCSContextBuilder withEndpoint(URI endpoint) { + addEndpointTo(endpoint, properties); + return this; + } + + // below is to cast the builder to the correct type so that chained builder methods end correctly + + @Override + public PCSContext buildContext() { + Injector injector = buildInjector(); + return injector.getInstance(PCSContext.class); + } + + @Override + public PCSContextBuilder relaxSSLHostname() { + return (PCSContextBuilder) super.relaxSSLHostname(); + } + + @Override + public PCSContextBuilder withExecutorService(ExecutorService service) { + return (PCSContextBuilder) super.withExecutorService(service); + } + + @Override + public PCSContextBuilder withHttpMaxRedirects(int httpMaxRedirects) { + return (PCSContextBuilder) super.withHttpMaxRedirects(httpMaxRedirects); + } + + @Override + public PCSContextBuilder withHttpMaxRetries(int httpMaxRetries) { + return (PCSContextBuilder) super.withHttpMaxRetries(httpMaxRetries); + } + + @Override + public PCSContextBuilder withJsonDebug() { + return (PCSContextBuilder) super.withJsonDebug(); + } + + @Override + public PCSContextBuilder withModule(Module module) { + return (PCSContextBuilder) super.withModule(module); + } + + @Override + public PCSContextBuilder withModules(Module... modules) { + return (PCSContextBuilder) super.withModules(modules); + } + + @Override + public PCSContextBuilder withPoolIoWorkerThreads(int poolIoWorkerThreads) { + return (PCSContextBuilder) super.withPoolIoWorkerThreads(poolIoWorkerThreads); + } + + @Override + public PCSContextBuilder withPoolMaxConnectionReuse(int poolMaxConnectionReuse) { + return (PCSContextBuilder) super.withPoolMaxConnectionReuse(poolMaxConnectionReuse); + } + + @Override + public PCSContextBuilder withPoolMaxConnections(int poolMaxConnections) { + return (PCSContextBuilder) super.withPoolMaxConnections(poolMaxConnections); + } + + @Override + public PCSContextBuilder withPoolMaxSessionFailures(int poolMaxSessionFailures) { + return (PCSContextBuilder) super.withPoolMaxSessionFailures(poolMaxSessionFailures); + } + + @Override + public PCSContextBuilder withPoolRequestInvokerThreads(int poolRequestInvokerThreads) { + return (PCSContextBuilder) super.withPoolRequestInvokerThreads(poolRequestInvokerThreads); + } + + @Override + public PCSContextBuilder withSaxDebug() { + return (PCSContextBuilder) super.withSaxDebug(); + } } diff --git a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/PCSContextFactory.java b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/PCSContextFactory.java new file mode 100644 index 0000000000..263e77eb67 --- /dev/null +++ b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/PCSContextFactory.java @@ -0,0 +1,51 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2; + +import java.net.URI; + +import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule; +import org.jclouds.logging.jdk.config.JDKLoggingModule; + +import com.google.inject.Module; + +/** + * Creates {@link PCSContext} instances based on the most commonly requested arguments. + *

+ * Note that Threadsafe objects will be bound as singletons to the Injector or Context provided. + *

+ *

+ * If no Modules are specified, the default {@link JDKLoggingModule logging} and + * {@link JavaUrlHttpCommandExecutorServiceModule http transports} will be installed. + * + * @author Adrian Cole + * @see PCSContext + */ +public class PCSContextFactory { + + public static PCSContext createContext(URI endpoint, String user, String key, Module... modules) { + return new PCSContextBuilder(endpoint, user, key).withEndpoint(endpoint).withModules(modules) + .buildContext(); + } +} diff --git a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/PCSUtil.java b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/PCSUtil.java new file mode 100644 index 0000000000..cf72a55e1e --- /dev/null +++ b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/PCSUtil.java @@ -0,0 +1,59 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2; + +import java.net.URI; + +import javax.ws.rs.GET; +import javax.ws.rs.PUT; + +import org.jclouds.http.filters.BasicAuthentication; +import org.jclouds.http.functions.ReturnFalseOn404; +import org.jclouds.rest.Endpoint; +import org.jclouds.rest.EntityParam; +import org.jclouds.rest.ExceptionParser; +import org.jclouds.rest.RequestFilters; +import org.jclouds.rest.SkipEncoding; + +/** + * Provides access to Mezeo PCS v2 via their REST API. + *

+ * + * @see + * @author Adrian Cole + */ +@SkipEncoding('/') +@RequestFilters(BasicAuthentication.class) +public interface PCSUtil { + + @PUT + @ExceptionParser(ReturnFalseOn404.class) + boolean put(@Endpoint URI resource, @EntityParam String value); + + @GET + String get(@Endpoint URI resource); + +} diff --git a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/binders/CreateContainerBinder.java b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/binders/CreateContainerBinder.java new file mode 100644 index 0000000000..de17d6e36c --- /dev/null +++ b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/binders/CreateContainerBinder.java @@ -0,0 +1,48 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.binders; + +import java.util.Collections; + +import javax.ws.rs.core.HttpHeaders; + +import org.jclouds.http.HttpRequest; +import org.jclouds.rest.binders.EntityBinder; + +/** + * + * @author Adrian Cole + * + */ +public class CreateContainerBinder implements EntityBinder { + + public void addEntityToRequest(Object toBind, HttpRequest request) { + String container = String.format("%s", toBind); + request.setEntity(container); + request.getHeaders().replaceValues(HttpHeaders.CONTENT_LENGTH, + Collections.singletonList(container.getBytes().length + "")); + request.getHeaders().replaceValues(HttpHeaders.CONTENT_TYPE, + Collections.singletonList("application/vnd.csp.container-info+xml")); + } +} diff --git a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/binders/PCSFileAsMultipartFormBinder.java b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/binders/PCSFileAsMultipartFormBinder.java new file mode 100644 index 0000000000..e8fccadbdf --- /dev/null +++ b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/binders/PCSFileAsMultipartFormBinder.java @@ -0,0 +1,88 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.binders; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.InputStream; + +import javax.ws.rs.core.HttpHeaders; + +import org.jclouds.blobstore.domain.Blob; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.MultipartForm; +import org.jclouds.http.MultipartForm.Part; +import org.jclouds.rest.binders.EntityBinder; + +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.Multimap; + +/** + * + * @author Adrian Cole + */ +public class PCSFileAsMultipartFormBinder implements EntityBinder { + + public static final String BOUNDARY = "--PCS--"; + + public void addEntityToRequest(Object entity, HttpRequest request) { + Blob object = (Blob) entity; + + Multimap partHeaders = ImmutableMultimap.of("Content-Disposition", + String.format("form-data; name=\"%s\"; filename=\"%s\"", object.getKey(), object + .getKey()), HttpHeaders.CONTENT_TYPE, checkNotNull(object.getMetadata() + .getContentType(), "object.metadata.contentType()")); + + Object data = checkNotNull(object.getData(), "object.getData()"); + + Part part; + try { + + if (data instanceof byte[]) { + part = new Part(partHeaders, (byte[]) data); + } else if (data instanceof String) { + part = new Part(partHeaders, (String) data); + } else if (data instanceof File) { + part = new Part(partHeaders, (File) data); + } else if (data instanceof InputStream) { + part = new Part(partHeaders, (InputStream) data, object.getContentLength()); + } else { + throw new IllegalArgumentException("type of part not supported: " + + data.getClass().getCanonicalName() + "; " + object); + } + } catch (FileNotFoundException e) { + throw new IllegalArgumentException("file for part not found: " + object); + } + MultipartForm form = new MultipartForm(BOUNDARY, part); + + request.setEntity(form.getData()); + request.getHeaders().put(HttpHeaders.CONTENT_TYPE, + "multipart/form-data; boundary=" + BOUNDARY); + + request.getHeaders().put(HttpHeaders.CONTENT_LENGTH, form.getSize() + ""); + + } +} diff --git a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/config/PCSContextModule.java b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/config/PCSContextModule.java new file mode 100644 index 0000000000..0fbc4a8d85 --- /dev/null +++ b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/config/PCSContextModule.java @@ -0,0 +1,104 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.config; + +import java.net.URI; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.TimeUnit; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Provider; +import javax.inject.Singleton; + +import org.jclouds.blobstore.BlobStoreContextImpl; +import org.jclouds.blobstore.BlobMap.Factory; +import org.jclouds.lifecycle.Closer; +import org.jclouds.mezeo.pcs2.PCS; +import org.jclouds.mezeo.pcs2.PCSBlobStore; +import org.jclouds.mezeo.pcs2.PCSContext; +import org.jclouds.mezeo.pcs2.domain.ContainerMetadata; +import org.jclouds.mezeo.pcs2.domain.FileMetadata; +import org.jclouds.mezeo.pcs2.domain.PCSFile; +import org.jclouds.mezeo.pcs2.functions.FindIdInContainerList; +import org.jclouds.mezeo.pcs2.functions.FindIdInFileList; +import org.jclouds.mezeo.pcs2.functions.Key; +import org.jclouds.mezeo.pcs2.reference.PCSConstants; + +import com.google.common.base.Function; +import com.google.common.collect.MapMaker; +import com.google.inject.AbstractModule; +import com.google.inject.Provides; +import com.google.inject.Scopes; + +/** + * Configures the PCS connection, including logging and http transport. + * + * @author Adrian Cole + */ +public class PCSContextModule extends AbstractModule { + @Override + protected void configure() { + bind(PCSContext.class).to(PCSContextImpl.class).in(Scopes.SINGLETON); + } + + public static class PCSContextImpl extends + BlobStoreContextImpl implements + PCSContext { + @Inject + PCSContextImpl(Factory blobMapFactory, + org.jclouds.blobstore.InputStreamMap.Factory inputStreamMapFactory, + Closer closer, Provider blobProvider, PCSBlobStore defaultApi, + @PCS URI endPoint, @Named(PCSConstants.PROPERTY_PCS2_USER) String account) { + super(blobMapFactory, inputStreamMapFactory, closer, blobProvider, defaultApi, endPoint, + account); + } + } + + @Provides + @Singleton + public ConcurrentMap provideConcurrentMap(FindIdInFileList finder) { + return new MapMaker().expiration(30, TimeUnit.SECONDS).makeComputingMap(finder); + } + + @Provides + @Singleton + public ConcurrentMap provideConcurrentMap(FindIdInContainerList finder) { + return new MapMaker().concurrencyLevel(32).expiration(30, TimeUnit.SECONDS).makeComputingMap( + finder); + } + + @Provides + @Singleton + public ConcurrentMap provideConcurrentMap(final PCSBlobStore connection) { + return new MapMaker().expiration(30, TimeUnit.SECONDS).makeComputingMap( + new Function() { + + public FileMetadata apply(Key from) { + return connection.blobMetadata(from.getContainer(), from.getKey()); + } + + }); + } +} \ No newline at end of file diff --git a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/config/RestPCSCloudModule.java b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/config/RestPCSBlobStoreModule.java similarity index 72% rename from mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/config/RestPCSCloudModule.java rename to mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/config/RestPCSBlobStoreModule.java index 785b5e4851..418edeffd9 100755 --- a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/config/RestPCSCloudModule.java +++ b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/config/RestPCSBlobStoreModule.java @@ -23,14 +23,22 @@ */ package org.jclouds.mezeo.pcs2.config; +import java.io.UnsupportedEncodingException; import java.net.URI; import javax.inject.Named; import javax.inject.Singleton; +import org.jclouds.cloud.ConfiguresCloudConnection; +import org.jclouds.concurrent.SingleThreaded; +import org.jclouds.http.HttpRetryHandler; import org.jclouds.http.RequiresHttp; +import org.jclouds.http.annotation.ClientError; +import org.jclouds.http.filters.BasicAuthentication; import org.jclouds.mezeo.pcs2.PCS; +import org.jclouds.mezeo.pcs2.PCSBlobStore; import org.jclouds.mezeo.pcs2.PCSCloud; +import org.jclouds.mezeo.pcs2.PCSUtil; import org.jclouds.mezeo.pcs2.PCSCloud.Response; import org.jclouds.mezeo.pcs2.endpoints.Contacts; import org.jclouds.mezeo.pcs2.endpoints.Metacontainers; @@ -39,9 +47,9 @@ import org.jclouds.mezeo.pcs2.endpoints.Recyclebin; import org.jclouds.mezeo.pcs2.endpoints.RootContainer; import org.jclouds.mezeo.pcs2.endpoints.Shares; import org.jclouds.mezeo.pcs2.endpoints.Tags; +import org.jclouds.mezeo.pcs2.handlers.PCSClientErrorRetryHandler; import org.jclouds.mezeo.pcs2.reference.PCSConstants; import org.jclouds.rest.RestClientFactory; -import org.jclouds.rest.config.JaxrsModule; import com.google.inject.AbstractModule; import com.google.inject.Provides; @@ -52,21 +60,44 @@ import com.google.inject.Provides; * @author Adrian Cole */ @RequiresHttp -public class RestPCSCloudModule extends AbstractModule { +@ConfiguresCloudConnection +@SingleThreaded +// http://code.google.com/p/jclouds/issues/detail?id=104 +public class RestPCSBlobStoreModule extends AbstractModule { @Override protected void configure() { - install(new JaxrsModule()); bindErrorHandlers(); bindRetryHandlers(); } + @Provides + @Singleton + public BasicAuthentication provideBasicAuthentication( + @Named(PCSConstants.PROPERTY_PCS2_USER) String user, + @Named(PCSConstants.PROPERTY_PCS2_PASSWORD) String password) + throws UnsupportedEncodingException { + return new BasicAuthentication(user, password); + } + @Provides @Singleton protected Response provideCloudResponse(RestClientFactory factory, @PCS URI authenticationUri) { return factory.create(PCSCloud.class).authenticate(); } + @Provides + @Singleton + protected PCSBlobStore provideConnection(RestClientFactory factory) { + return factory.create(PCSBlobStore.class); + } + + @Provides + @Singleton + protected PCSUtil providePCSUtil(RestClientFactory factory) { + return factory.create(PCSUtil.class); + } + @Provides @Singleton @PCS @@ -129,7 +160,8 @@ public class RestPCSCloudModule extends AbstractModule { } protected void bindRetryHandlers() { - // TODO retry on 401 by AuthenticateRequest.update() + bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to( + PCSClientErrorRetryHandler.class); } } \ No newline at end of file diff --git a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/domain/ContainerMetadata.java b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/domain/ContainerMetadata.java new file mode 100644 index 0000000000..5d09b79ab5 --- /dev/null +++ b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/domain/ContainerMetadata.java @@ -0,0 +1,171 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.domain; + +import java.net.URI; + +import org.joda.time.DateTime; + +/** + * + * @author Adrian Cole + * + */ +public class ContainerMetadata extends org.jclouds.blobstore.domain.ContainerMetadata implements + PCSObject { + private URI url; + private DateTime created; + private DateTime lastModified; + private DateTime accessed; + private String owner; + private boolean isShared; + private boolean isInProject; + private int version; + private long bytes; + + @Override + public String toString() { + return "ContainerMetadata [name=" + name + ", url=" + url + ", accessed=" + accessed + + ", bytes=" + bytes + ", created=" + created + ", isInProject=" + isInProject + + ", isShared=" + isShared + ", lastModified=" + lastModified + ", owner=" + owner + + ", version=" + version + "]"; + } + + @Override + public int hashCode() { + int prime = 31; + int result = super.hashCode(); + result = prime * result + ((accessed == null) ? 0 : accessed.hashCode()); + result = prime * result + (int) (bytes ^ (bytes >>> 32)); + result = prime * result + ((created == null) ? 0 : created.hashCode()); + result = prime * result + (isInProject ? 1231 : 1237); + result = prime * result + (isShared ? 1231 : 1237); + result = prime * result + ((lastModified == null) ? 0 : lastModified.hashCode()); + result = prime * result + ((owner == null) ? 0 : owner.hashCode()); + result = prime * result + ((url == null) ? 0 : url.hashCode()); + result = prime * result + version; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + ContainerMetadata other = (ContainerMetadata) obj; + if (accessed == null) { + if (other.accessed != null) + return false; + } else if (!accessed.equals(other.accessed)) + return false; + if (bytes != other.bytes) + return false; + if (created == null) { + if (other.created != null) + return false; + } else if (!created.equals(other.created)) + return false; + if (isInProject != other.isInProject) + return false; + if (isShared != other.isShared) + return false; + if (lastModified == null) { + if (other.lastModified != null) + return false; + } else if (!lastModified.equals(other.lastModified)) + return false; + if (owner == null) { + if (other.owner != null) + return false; + } else if (!owner.equals(other.owner)) + return false; + if (url == null) { + if (other.url != null) + return false; + } else if (!url.equals(other.url)) + return false; + if (version != other.version) + return false; + return true; + } + + public ContainerMetadata() { + super(); + } + + public ContainerMetadata(String name, URI url, DateTime created, DateTime lastModified, + DateTime accessed, String owner, boolean isShared, boolean isInProject, int version, + long bytes) { + super(name); + this.url = url; + this.created = created; + this.lastModified = lastModified; + this.accessed = accessed; + this.owner = owner; + this.isShared = isShared; + this.isInProject = isInProject; + this.version = version; + this.bytes = bytes; + } + + public URI getUrl() { + return url; + } + + public DateTime getCreated() { + return created; + } + + public DateTime getLastModified() { + return lastModified; + } + + public DateTime getAccessed() { + return accessed; + } + + public String getOwner() { + return owner; + } + + public boolean isShared() { + return isShared; + } + + public boolean isInProject() { + return isInProject; + } + + public int getVersion() { + return version; + } + + public long getSize() { + return bytes; + } + +} diff --git a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/domain/FileMetadata.java b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/domain/FileMetadata.java new file mode 100644 index 0000000000..d447c945e5 --- /dev/null +++ b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/domain/FileMetadata.java @@ -0,0 +1,189 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.domain; + +import java.net.URI; +import java.util.Arrays; + +import org.jclouds.mezeo.pcs2.util.PCSUtils; +import org.joda.time.DateTime; + +/** + * + * @author Adrian Cole + * + */ +public class FileMetadata extends org.jclouds.blobstore.domain.BlobMetadata { + /** The serialVersionUID */ + private static final long serialVersionUID = 1L; + private URI url; + private DateTime created; + private DateTime accessed; + private String owner; + private Boolean isShared; + private Boolean isInProject; + private Integer version; + private Boolean isPublic; + + @Override + public String toString() { + return "FileMetadata [key=" + key + ", created=" + created + ", isInProject=" + isInProject + + ", isPublic=" + isPublic + ", isShared=" + isShared + ", owner=" + owner + + ", url=" + url + ", version=" + version + ", allHeaders=" + allHeaders + + ", dataType=" + dataType + ", eTag=" + Arrays.toString(eTag) + ", accessed=" + + accessed + ", lastModified=" + lastModified + ", size=" + size + ", userMetadata=" + + userMetadata + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((accessed == null) ? 0 : accessed.hashCode()); + result = prime * result + ((created == null) ? 0 : created.hashCode()); + result = prime * result + ((isInProject == null) ? 0 : isInProject.hashCode()); + result = prime * result + ((isPublic == null) ? 0 : isPublic.hashCode()); + result = prime * result + ((isShared == null) ? 0 : isShared.hashCode()); + result = prime * result + ((owner == null) ? 0 : owner.hashCode()); + result = prime * result + ((url == null) ? 0 : url.hashCode()); + result = prime * result + ((version == null) ? 0 : version.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + FileMetadata other = (FileMetadata) obj; + if (accessed == null) { + if (other.accessed != null) + return false; + } else if (!accessed.equals(other.accessed)) + return false; + if (created == null) { + if (other.created != null) + return false; + } else if (!created.equals(other.created)) + return false; + if (isInProject == null) { + if (other.isInProject != null) + return false; + } else if (!isInProject.equals(other.isInProject)) + return false; + if (isPublic == null) { + if (other.isPublic != null) + return false; + } else if (!isPublic.equals(other.isPublic)) + return false; + if (isShared == null) { + if (other.isShared != null) + return false; + } else if (!isShared.equals(other.isShared)) + return false; + if (owner == null) { + if (other.owner != null) + return false; + } else if (!owner.equals(other.owner)) + return false; + if (url == null) { + if (other.url != null) + return false; + } else if (!url.equals(other.url)) + return false; + if (version == null) { + if (other.version != null) + return false; + } else if (!version.equals(other.version)) + return false; + return true; + } + + public FileMetadata(String name, URI url, DateTime created, DateTime lastModified, + DateTime accessed, String owner, boolean isShared, boolean isInProject, int version, + long bytes, String contentType, boolean isPublic) { + super(name); + setLastModified(lastModified); + setSize(bytes); + setContentType(contentType); + this.url = url; + this.created = created; + this.accessed = accessed; + this.owner = owner; + this.isShared = isShared; + this.isInProject = isInProject; + this.version = version; + this.isPublic = isPublic; + byte[] eTag = PCSUtils.getEtag(url); + setETag(eTag); + } + + public FileMetadata(String key) { + super(key); + } + + public FileMetadata() { + super(); + } + + public URI getUrl() { + return url; + } + + public DateTime getCreated() { + return created; + } + + public DateTime getLastModified() { + return lastModified; + } + + public DateTime getAccessed() { + return accessed; + } + + public String getOwner() { + return owner; + } + + public Boolean isShared() { + return isShared; + } + + public Boolean isInProject() { + return isInProject; + } + + public Integer getVersion() { + return version; + } + + public Boolean isPublic() { + return isPublic; + } + +} diff --git a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/domain/PCSFile.java b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/domain/PCSFile.java new file mode 100644 index 0000000000..d64fc7504f --- /dev/null +++ b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/domain/PCSFile.java @@ -0,0 +1,51 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.domain; + + +/** + * @author Adrian Cole + */ +public class PCSFile extends org.jclouds.blobstore.domain.Blob { + + public PCSFile(FileMetadata metadata, FileMetadata data) { + super(metadata, data); + } + + public PCSFile(FileMetadata metadata) { + super(metadata); + } + + public PCSFile(String key, FileMetadata data) { + this(new FileMetadata(key), data); + } + + public PCSFile(String key) { + this(new FileMetadata(key)); + } + + public PCSFile() { + this(new FileMetadata()); + } +} diff --git a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/domain/PCSObject.java b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/domain/PCSObject.java new file mode 100644 index 0000000000..0c42f222cf --- /dev/null +++ b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/domain/PCSObject.java @@ -0,0 +1,57 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.domain; + +import java.net.URI; + +import org.joda.time.DateTime; + +/** + * + * @author Adrian Cole + * + */ +public interface PCSObject { + + URI getUrl(); + + String getName(); + + DateTime getCreated(); + + DateTime getLastModified(); + + DateTime getAccessed(); + + String getOwner(); + + boolean isShared(); + + boolean isInProject(); + + int getVersion(); + + long getSize(); + +} \ No newline at end of file diff --git a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/AddMetadataAndParseResourceIdIntoBytes.java b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/AddMetadataAndParseResourceIdIntoBytes.java new file mode 100644 index 0000000000..892ec9a2e7 --- /dev/null +++ b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/AddMetadataAndParseResourceIdIntoBytes.java @@ -0,0 +1,104 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.functions; + +import static com.google.common.base.Preconditions.checkState; + +import java.io.IOException; +import java.net.URI; +import java.util.Map.Entry; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.ws.rs.core.UriBuilder; + +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.HttpResponseException; +import org.jclouds.logging.Logger; +import org.jclouds.mezeo.pcs2.PCSUtil; +import org.jclouds.mezeo.pcs2.domain.PCSFile; +import org.jclouds.mezeo.pcs2.util.PCSUtils; +import org.jclouds.rest.RestContext; +import org.jclouds.util.Utils; + +import com.google.common.base.Function; + +/** + * PCS does not return an eTag header. As such, we'll make one out of the object id. + * + * @author Adrian Cole + */ +public class AddMetadataAndParseResourceIdIntoBytes implements Function, + RestContext { + private final PCSUtil util; + @Resource + protected Logger logger = Logger.NULL; + private Object[] args; + private HttpRequest request; + + @Inject + public AddMetadataAndParseResourceIdIntoBytes(PCSUtil util) { + this.util = util; + } + + public byte[] apply(HttpResponse from) { + checkState(args != null, "args should be initialized at this point"); + PCSFile file = null; + for (Object arg : args) { + if (arg instanceof PCSFile) + file = (PCSFile) arg; + } + checkState(file != null, "No PCSFile found in args, improper method declarations"); + checkState(request != null, "request should be initialized at this point"); + + try { + String toParse = Utils.toStringAndClose(from.getContent()); + logger.trace("%s: received the following response: %s", from, toParse); + URI uri = URI.create(toParse.trim()); + for (Entry entry : file.getMetadata().getUserMetadata().entries()) { + URI key = UriBuilder.fromUri(uri).path(String.format("metadata/%s", entry.getKey())) + .build(); + util.put(key, entry.getValue()); + } + return PCSUtils.getEtag(uri); + } catch (IOException e) { + throw new HttpResponseException("couldn't parse url from response", null, from, e); + } + } + + public Object[] getArgs() { + return args; + } + + public HttpRequest getRequest() { + return request; + } + + public void setContext(HttpRequest request, Object[] args) { + this.request = request; + this.args = args; + } + +} \ No newline at end of file diff --git a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/AssembleBlobFromContentAndMetadataCache.java b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/AssembleBlobFromContentAndMetadataCache.java new file mode 100644 index 0000000000..94c253b20b --- /dev/null +++ b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/AssembleBlobFromContentAndMetadataCache.java @@ -0,0 +1,78 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.functions; + +import java.util.concurrent.ConcurrentMap; + +import javax.inject.Inject; + +import org.jclouds.blobstore.functions.ParseContentTypeFromHeaders; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.mezeo.pcs2.domain.FileMetadata; +import org.jclouds.mezeo.pcs2.domain.PCSFile; +import org.jclouds.rest.RestContext; + +import com.google.common.base.Function; + +/** + * Parses response headers and creates a new PCSFile from them and the HTTP content. + * + * @see ParseContentTypeFromHeaders + * @author Adrian Cole + */ +public class AssembleBlobFromContentAndMetadataCache implements Function, + RestContext { + + private final ConcurrentMap cache; + private HttpRequest request; + private Object[] args; + + @Inject + public AssembleBlobFromContentAndMetadataCache(ConcurrentMap cache) { + this.cache = cache; + } + + public PCSFile apply(HttpResponse from) { + FileMetadata metadata = cache.get(new Key(getArgs()[0].toString(), this.getArgs()[1].toString())); + PCSFile blob = new PCSFile(metadata); + blob.setData(from.getContent()); + blob.setContentLength(metadata.getSize()); + return blob; + } + + public Object[] getArgs() { + return args; + } + + public HttpRequest getRequest() { + return request; + } + + public void setContext(HttpRequest request, Object[] args) { + this.args = args; + this.request = request; + } + +} \ No newline at end of file diff --git a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/ContainerAndFileNameToResourceId.java b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/ContainerAndFileNameToResourceId.java new file mode 100644 index 0000000000..185dafdc10 --- /dev/null +++ b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/ContainerAndFileNameToResourceId.java @@ -0,0 +1,74 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.functions; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; + +import java.util.concurrent.ConcurrentMap; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.blobstore.ContainerNotFoundException; +import org.jclouds.blobstore.KeyNotFoundException; +import org.jclouds.util.Utils; + +import com.google.common.base.Function; +import com.google.common.collect.ComputationException; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class ContainerAndFileNameToResourceId implements Function { + + private ConcurrentMap cachedFinder; + + @Inject + public ContainerAndFileNameToResourceId(ConcurrentMap cachedFinder) { + this.cachedFinder = cachedFinder; + } + + public String apply(Object from) { + checkState(checkNotNull(from, "args") instanceof Object[], + "this must be applied to a method!"); + Object[] args = (Object[]) from; + checkArgument(args[0] instanceof String, "arg[0] must be a container name"); + checkArgument(args[1] instanceof String, "arg[1] must be a pcsfile name (key)"); + + String container = args[0].toString(); + String key = args[1].toString(); + try { + return cachedFinder.get(new Key(container, key)); + } catch (ComputationException e) { + Utils. rethrowIfRuntimeOrSameType(e); + Utils. rethrowIfRuntimeOrSameType(e); + throw e; + } + } + +} \ No newline at end of file diff --git a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/ContainerNameToResourceId.java b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/ContainerNameToResourceId.java new file mode 100644 index 0000000000..a74388bee9 --- /dev/null +++ b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/ContainerNameToResourceId.java @@ -0,0 +1,63 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.functions; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.concurrent.ConcurrentMap; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.blobstore.ContainerNotFoundException; +import org.jclouds.util.Utils; + +import com.google.common.base.Function; +import com.google.common.collect.ComputationException; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class ContainerNameToResourceId implements Function { + + private final ConcurrentMap finder; + + @Inject + public ContainerNameToResourceId(ConcurrentMap finder) { + this.finder = finder; + } + + public String apply(Object from) { + String toFind = checkNotNull(from, "name").toString(); + try { + return finder.get(toFind); + } catch (ComputationException e) { + Utils. rethrowIfRuntimeOrSameType(e); + throw e; + } + } + +} \ No newline at end of file diff --git a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/FindIdInContainerList.java b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/FindIdInContainerList.java new file mode 100644 index 0000000000..d9456627bd --- /dev/null +++ b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/FindIdInContainerList.java @@ -0,0 +1,39 @@ +package org.jclouds.mezeo.pcs2.functions; + +import java.util.List; + +import javax.inject.Inject; + +import org.jclouds.blobstore.ContainerNotFoundException; +import org.jclouds.mezeo.pcs2.PCSBlobStore; +import org.jclouds.mezeo.pcs2.domain.ContainerMetadata; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Function; + +public class FindIdInContainerList implements Function { + private PCSBlobStore connection; + + @Inject + public FindIdInContainerList(PCSBlobStore connection) { + this.connection = connection; + } + + public String apply(String key) { + List response = connection.listContainers(); + return idForNameInListOrException(key, response); + } + + @VisibleForTesting + String idForNameInListOrException(String toFind, List containerMetadataList) { + for (ContainerMetadata data : containerMetadataList) { + if (toFind.equals(data.getName())) { + String path = data.getUrl().getPath(); + int indexAfterContainersSlash = path.indexOf("containers/") + "containers/".length(); + return path.substring(indexAfterContainersSlash); + } + } + throw new ContainerNotFoundException(toFind); + } + +} \ No newline at end of file diff --git a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/FindIdInFileList.java b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/FindIdInFileList.java new file mode 100644 index 0000000000..b16ba2c1f2 --- /dev/null +++ b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/FindIdInFileList.java @@ -0,0 +1,50 @@ +package org.jclouds.mezeo.pcs2.functions; + +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import javax.inject.Inject; + +import org.jclouds.blobstore.ContainerNotFoundException; +import org.jclouds.blobstore.KeyNotFoundException; +import org.jclouds.http.HttpException; +import org.jclouds.mezeo.pcs2.PCSBlobStore; +import org.jclouds.mezeo.pcs2.domain.FileMetadata; +import org.jclouds.util.Utils; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Function; + +public class FindIdInFileList implements Function { + private PCSBlobStore connection; + + @Inject + public FindIdInFileList(PCSBlobStore connection) { + this.connection = connection; + } + + public String apply(Key key) { + List response; + try { + response = connection.listBlobs(key.getContainer()).get(10, TimeUnit.SECONDS); + } catch (Exception e) { + Utils. rethrowIfRuntimeOrSameType(e); + throw new HttpException("could not list blobs for " + Arrays.asList(key.getContainer()), e); + } + return idForNameInListOrException(key.getContainer(), key.getKey(), response); + } + + @VisibleForTesting + String idForNameInListOrException(String container, String toFind, List response) { + for (FileMetadata data : response) { + if (toFind.equals(data.getKey())) { + String path = data.getUrl().getPath(); + int indexAfterContainersSlash = path.indexOf("files/") + "files/".length(); + return path.substring(indexAfterContainersSlash); + } + } + throw new KeyNotFoundException(container, toFind); + } + +} \ No newline at end of file diff --git a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/InvalidateContainerNameCacheAndReturnTrueIf2xx.java b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/InvalidateContainerNameCacheAndReturnTrueIf2xx.java new file mode 100644 index 0000000000..7060765fa0 --- /dev/null +++ b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/InvalidateContainerNameCacheAndReturnTrueIf2xx.java @@ -0,0 +1,53 @@ +package org.jclouds.mezeo.pcs2.functions; + +import java.util.concurrent.ConcurrentMap; + +import javax.inject.Inject; + +import org.apache.commons.io.IOUtils; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.rest.RestContext; + +import com.google.common.base.Function; + +/** + * invalidates cache and returns true when the http response code is in the range 200-299. + * + * @author Adrian Cole + */ +public class InvalidateContainerNameCacheAndReturnTrueIf2xx implements Function, + RestContext { + private final ConcurrentMap cache; + private HttpRequest request; + private Object[] args; + + @Inject + public InvalidateContainerNameCacheAndReturnTrueIf2xx(ConcurrentMap cache) { + this.cache = cache; + } + + public Boolean apply(HttpResponse from) { + IOUtils.closeQuietly(from.getContent()); + int code = from.getStatusCode(); + if (code >= 300 || code < 200) { + throw new IllegalStateException("incorrect code for this operation: " + from); + } + cache.remove(getArgs()[0]); + return true; + } + + public Object[] getArgs() { + return args; + } + + public HttpRequest getRequest() { + return request; + } + + public void setContext(HttpRequest request, Object[] args) { + this.args = args; + this.request = request; + } + +} \ No newline at end of file diff --git a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/InvalidatePCSKeyCacheAndReturnTrueIf2xx.java b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/InvalidatePCSKeyCacheAndReturnTrueIf2xx.java new file mode 100644 index 0000000000..d9a5a5edb7 --- /dev/null +++ b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/InvalidatePCSKeyCacheAndReturnTrueIf2xx.java @@ -0,0 +1,59 @@ +package org.jclouds.mezeo.pcs2.functions; + +import java.util.concurrent.ConcurrentMap; + +import javax.inject.Inject; + +import org.apache.commons.io.IOUtils; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.mezeo.pcs2.domain.FileMetadata; +import org.jclouds.rest.RestContext; + +import com.google.common.base.Function; + +/** + * invalidates cache and returns true when the http response code is in the range 200-299. + * + * @author Adrian Cole + */ +public class InvalidatePCSKeyCacheAndReturnTrueIf2xx implements Function, + RestContext { + private final ConcurrentMap cache; + private final ConcurrentMap mdCache; + private HttpRequest request; + private Object[] args; + + @Inject + public InvalidatePCSKeyCacheAndReturnTrueIf2xx(ConcurrentMap cache, + ConcurrentMap mdCache) { + this.cache = cache; + this.mdCache = mdCache; + } + + public Boolean apply(HttpResponse from) { + IOUtils.closeQuietly(from.getContent()); + int code = from.getStatusCode(); + if (code >= 300 || code < 200) { + throw new IllegalStateException("incorrect code for this operation: " + from); + } + Key key = new Key(getArgs()[0].toString(), getArgs()[1].toString()); + cache.remove(key); + mdCache.remove(key); + return true; + } + + public Object[] getArgs() { + return args; + } + + public HttpRequest getRequest() { + return request; + } + + public void setContext(HttpRequest request, Object[] args) { + this.args = args; + this.request = request; + } + +} \ No newline at end of file diff --git a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/Key.java b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/Key.java new file mode 100644 index 0000000000..e57fef0905 --- /dev/null +++ b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/Key.java @@ -0,0 +1,51 @@ +package org.jclouds.mezeo.pcs2.functions; + +public class Key { + private final String container; + private final String key; + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((getContainer() == null) ? 0 : getContainer().hashCode()); + result = prime * result + ((getKey() == null) ? 0 : getKey().hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Key other = (Key) obj; + if (getContainer() == null) { + if (other.getContainer() != null) + return false; + } else if (!getContainer().equals(other.getContainer())) + return false; + if (getKey() == null) { + if (other.getKey() != null) + return false; + } else if (!getKey().equals(other.getKey())) + return false; + return true; + } + + public Key(String container, String key) { + super(); + this.container = container; + this.key = key; + } + + public String getContainer() { + return container; + } + + public String getKey() { + return key; + } +} \ No newline at end of file diff --git a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/ReturnFalseIfContainerNotFound.java b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/ReturnFalseIfContainerNotFound.java new file mode 100644 index 0000000000..2de9503832 --- /dev/null +++ b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/ReturnFalseIfContainerNotFound.java @@ -0,0 +1,43 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.functions; + +import org.jclouds.blobstore.ContainerNotFoundException; + +import com.google.common.base.Function; + +/** + * + * @author Adrian Cole + */ +public class ReturnFalseIfContainerNotFound implements Function { + + public Boolean apply(Exception from) { + if (from instanceof ContainerNotFoundException) { + return false; + } + return null; + } + +} diff --git a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/ReturnTrueIfContainerAlreadyExists.java b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/ReturnTrueIfContainerAlreadyExists.java new file mode 100644 index 0000000000..2ebeab6633 --- /dev/null +++ b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/ReturnTrueIfContainerAlreadyExists.java @@ -0,0 +1,46 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.functions; + +import org.jclouds.http.HttpResponseException; + +import com.google.common.base.Function; + +/** + * + * @author Adrian Cole + */ +public class ReturnTrueIfContainerAlreadyExists implements Function { + + public Boolean apply(Exception from) { + if (from instanceof HttpResponseException) { + HttpResponseException responseException = (HttpResponseException) from; + if ("The directory already exists.".equals(responseException.getContent())) { + return true; + } + } + return null; + } + +} diff --git a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/ReturnTrueIfContainerNotFound.java b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/ReturnTrueIfContainerNotFound.java new file mode 100644 index 0000000000..bcbcee3bb6 --- /dev/null +++ b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/ReturnTrueIfContainerNotFound.java @@ -0,0 +1,43 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.functions; + +import org.jclouds.blobstore.ContainerNotFoundException; + +import com.google.common.base.Function; + +/** + * + * @author Adrian Cole + */ +public class ReturnTrueIfContainerNotFound implements Function { + + public Boolean apply(Exception from) { + if (from instanceof ContainerNotFoundException) { + return true; + } + return null; + } + +} diff --git a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/handlers/PCSClientErrorRetryHandler.java b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/handlers/PCSClientErrorRetryHandler.java new file mode 100644 index 0000000000..66fe8b898a --- /dev/null +++ b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/handlers/PCSClientErrorRetryHandler.java @@ -0,0 +1,36 @@ +package org.jclouds.mezeo.pcs2.handlers; + +import javax.annotation.Resource; +import javax.inject.Inject; + +import org.jclouds.http.HttpCommand; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.HttpRetryHandler; +import org.jclouds.http.handlers.BackoffLimitedRetryHandler; +import org.jclouds.logging.Logger; + +/** + * Handles Retryable responses with error codes in the 4xx range + * + * @author Adrian Cole + */ +public class PCSClientErrorRetryHandler implements HttpRetryHandler { + + private final BackoffLimitedRetryHandler backoffHandler; + + @Inject + public PCSClientErrorRetryHandler(BackoffLimitedRetryHandler backoffHandler) { + this.backoffHandler = backoffHandler; + } + + @Resource + protected Logger logger = Logger.NULL; + + public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) { + if (response.getStatusCode() == 400) { + return backoffHandler.shouldRetryRequest(command, response); + } + return false; + } + +} diff --git a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/util/PCSUtils.java b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/util/PCSUtils.java new file mode 100644 index 0000000000..f16e1e6aee --- /dev/null +++ b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/util/PCSUtils.java @@ -0,0 +1,47 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.util; + +import java.net.URI; + +import org.jclouds.http.HttpUtils; + +/** + * Utilities for PCS connections. + * + * @author Adrian Cole + */ +public class PCSUtils { + /** + * converts the object id into something we can use as an etag + */ + public static byte[] getEtag(URI url) { + String id = url.getPath().substring(url.getPath().lastIndexOf('/') + 1); + id = id.replaceAll("-", ""); + // parse url to create an "etag" + byte[] eTag = HttpUtils.fromHexString(id); + return eTag; + } + +} diff --git a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/xml/BaseFileMetadataHandler.java b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/xml/BaseFileMetadataHandler.java new file mode 100644 index 0000000000..a54fa7994d --- /dev/null +++ b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/xml/BaseFileMetadataHandler.java @@ -0,0 +1,112 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.xml; + +import java.net.URI; + +import javax.inject.Inject; + +import org.jclouds.http.functions.ParseSax; +import org.jclouds.mezeo.pcs2.domain.FileMetadata; +import org.jclouds.util.DateService; +import org.joda.time.DateTime; + +/** + * @author Adrian Cole + */ +public abstract class BaseFileMetadataHandler extends ParseSax.HandlerWithResult { + + protected URI currentUrl; + private String currentName; + private DateTime currentCreated; + private boolean currentInproject; + private DateTime currentModified; + private String currentOwner; + private int currentVersion; + private boolean currentShared; + private DateTime currentAccessed; + private long currentBytes; + private String currentMimeType; + private boolean currentPublic; + + protected StringBuilder currentText = new StringBuilder(); + + private final DateService dateParser; + + @Inject + public BaseFileMetadataHandler(DateService dateParser) { + this.dateParser = dateParser; + } + + @Override + public void endElement(String uri, String name, String qName) { + if (qName.equals("name")) { + currentName = currentText.toString().trim(); + } else if (qName.equals("created")) { + currentCreated = dateParser.fromSeconds(Long.parseLong(currentText.toString().trim())); + } else if (qName.equals("inproject")) { + currentInproject = Boolean.parseBoolean(currentText.toString().trim()); + } else if (qName.equals("modified")) { + currentModified = dateParser.fromSeconds(Long.parseLong(currentText.toString().trim())); + } else if (qName.equals("owner")) { + currentOwner = currentText.toString().trim(); + } else if (qName.equals("version")) { + currentVersion = Integer.parseInt(currentText.toString().trim()); + } else if (qName.equals("shared")) { + currentShared = Boolean.parseBoolean(currentText.toString().trim()); + } else if (qName.equals("accessed")) { + currentAccessed = dateParser.fromSeconds(Long.parseLong(currentText.toString().trim())); + } else if (qName.equals("bytes")) { + currentBytes = Long.parseLong(currentText.toString().trim()); + } else if (qName.equals("mime_type")) { + currentMimeType = currentText.toString().trim(); + } else if (qName.equals("public")) { + currentPublic = Boolean.parseBoolean(currentText.toString().trim()); + } else if (qName.equals("file")) { + FileMetadata metadata = new FileMetadata(currentName, currentUrl, currentCreated, + currentModified, currentAccessed, currentOwner, currentShared, currentInproject, + currentVersion, currentBytes, currentMimeType, currentPublic); + addFileMetadata(metadata); + currentUrl = null; + currentName = null; + currentCreated = null; + currentInproject = false; + currentModified = null; + currentOwner = null; + currentVersion = 0; + currentShared = false; + currentAccessed = null; + currentBytes = 0; + currentMimeType = null; + currentPublic = false; + } + currentText = new StringBuilder(); + } + + protected abstract void addFileMetadata(FileMetadata metadata); + + public void characters(char ch[], int start, int length) { + currentText.append(ch, start, length); + } +} diff --git a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/xml/FileListToContainerMetadataListHandler.java b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/xml/FileListToContainerMetadataListHandler.java new file mode 100755 index 0000000000..b351d41be1 --- /dev/null +++ b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/xml/FileListToContainerMetadataListHandler.java @@ -0,0 +1,123 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.xml; + +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; + +import org.jclouds.http.functions.ParseSax; +import org.jclouds.mezeo.pcs2.domain.ContainerMetadata; +import org.jclouds.util.DateService; +import org.joda.time.DateTime; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + +/** + * @author Adrian Cole + */ +public class FileListToContainerMetadataListHandler extends + ParseSax.HandlerWithResult> { + + private List containerMetadata = new ArrayList(); + private URI currentUrl; + private String currentName; + private DateTime currentCreated; + private boolean currentInproject; + private DateTime currentModified; + private String currentOwner; + private int currentVersion; + private boolean currentShared; + private DateTime currentAccessed; + private long currentBytes; + + private StringBuilder currentText = new StringBuilder(); + + private final DateService dateParser; + + @Inject + public FileListToContainerMetadataListHandler(DateService dateParser) { + this.dateParser = dateParser; + } + + public List getResult() { + return containerMetadata; + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) + throws SAXException { + if (qName.equals("container")) { + int index = attributes.getIndex("xlink:href"); + if (index != -1) { + currentUrl = URI.create(attributes.getValue(index)); + } + } + } + + @Override + public void endElement(String uri, String name, String qName) { + if (qName.equals("name")) { + currentName = currentText.toString().trim(); + } else if (qName.equals("created")) { + currentCreated = dateParser.fromSeconds(Long.parseLong(currentText.toString().trim())); + } else if (qName.equals("inproject")) { + currentInproject = Boolean.parseBoolean(currentText.toString().trim()); + } else if (qName.equals("modified")) { + currentModified = dateParser.fromSeconds(Long.parseLong(currentText.toString().trim())); + } else if (qName.equals("owner")) { + currentOwner = currentText.toString().trim(); + } else if (qName.equals("version")) { + currentVersion = Integer.parseInt(currentText.toString().trim()); + } else if (qName.equals("shared")) { + currentShared = Boolean.parseBoolean(currentText.toString().trim()); + } else if (qName.equals("accessed")) { + currentAccessed = dateParser.fromSeconds(Long.parseLong(currentText.toString().trim())); + } else if (qName.equals("bytes")) { + currentBytes = Long.parseLong(currentText.toString().trim()); + } else if (qName.equals("container")) { + containerMetadata.add(new ContainerMetadata(currentName, currentUrl, currentCreated, + currentModified, currentAccessed, currentOwner, currentShared, currentInproject, + currentVersion, currentBytes)); + currentUrl = null; + currentName = null; + currentCreated = null; + currentInproject = false; + currentModified = null; + currentOwner = null; + currentVersion = 0; + currentShared = false; + currentAccessed = null; + currentBytes = 0; + + } + currentText = new StringBuilder(); + } + + public void characters(char ch[], int start, int length) { + currentText.append(ch, start, length); + } +} diff --git a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/xml/FileListToFileMetadataListHandler.java b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/xml/FileListToFileMetadataListHandler.java new file mode 100644 index 0000000000..9d405de161 --- /dev/null +++ b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/xml/FileListToFileMetadataListHandler.java @@ -0,0 +1,68 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.xml; + +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; + +import org.jclouds.mezeo.pcs2.domain.FileMetadata; +import org.jclouds.util.DateService; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + +/** + * @author Adrian Cole + */ +public class FileListToFileMetadataListHandler extends +BaseFileMetadataHandler> { + + private List containerMetadata = new ArrayList(); + + @Inject + public FileListToFileMetadataListHandler(DateService dateParser) { + super(dateParser); + } + + public List getResult() { + return containerMetadata; + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) + throws SAXException { + if (qName.equals("file")) { + int index = attributes.getIndex("xlink:href"); + if (index != -1) { + currentUrl = URI.create(attributes.getValue(index)); + } + } + } + + protected void addFileMetadata(FileMetadata metadata) { + containerMetadata.add(metadata); + } +} diff --git a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/xml/FileMetadataHandler.java b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/xml/FileMetadataHandler.java new file mode 100644 index 0000000000..066129b50f --- /dev/null +++ b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/xml/FileMetadataHandler.java @@ -0,0 +1,79 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.xml; + +import java.net.URI; + +import javax.inject.Inject; + +import org.jclouds.mezeo.pcs2.PCSUtil; +import org.jclouds.mezeo.pcs2.domain.FileMetadata; +import org.jclouds.util.DateService; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; + +/** + * @author Adrian Cole + */ +public class FileMetadataHandler extends BaseFileMetadataHandler { + private final PCSUtil util; + private FileMetadata fileMetadata = null; + protected Multimap userMetadata = HashMultimap.create(); + + @Inject + public FileMetadataHandler(PCSUtil util, DateService dateParser) { + super(dateParser); + this.util = util; + } + + public FileMetadata getResult() { + return fileMetadata; + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) + throws SAXException { + if (qName.equals("content")) { + int index = attributes.getIndex("xlink:href"); + if (index != -1) { + currentUrl = URI.create(attributes.getValue(index).replaceAll("/content", "")); + } + } else if (qName.equals("metadata-item")) { + int index = attributes.getIndex("xlink:href"); + if (index != -1) { + String key = attributes.getValue(index).replaceAll(".*/metadata/", ""); + String value = util.get(URI.create(attributes.getValue(index))).trim(); + userMetadata.put(key.toLowerCase(), value); + } + } + } + + protected void addFileMetadata(FileMetadata metadata) { + this.fileMetadata = metadata; + this.fileMetadata.setUserMetadata(userMetadata); + } +} diff --git a/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/PCSBlobStoreLiveTest.java b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/PCSBlobStoreLiveTest.java new file mode 100644 index 0000000000..404269275e --- /dev/null +++ b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/PCSBlobStoreLiveTest.java @@ -0,0 +1,203 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; + +import java.io.InputStream; +import java.net.URI; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.io.IOUtils; +import org.jclouds.blobstore.KeyNotFoundException; +import org.jclouds.blobstore.integration.internal.BaseBlobStoreIntegrationTest; +import org.jclouds.http.HttpResponseException; +import org.jclouds.http.HttpUtils; +import org.jclouds.logging.log4j.config.Log4JLoggingModule; +import org.jclouds.mezeo.pcs2.domain.ContainerMetadata; +import org.jclouds.mezeo.pcs2.domain.FileMetadata; +import org.jclouds.mezeo.pcs2.domain.PCSFile; +import org.testng.annotations.BeforeGroups; +import org.testng.annotations.Test; + +import com.google.common.collect.Iterables; + +/** + * Tests behavior of {@code PCSDiscovery} + * + * @author Adrian Cole + */ +@Test(groups = "live", testName = "pcs2.PCSConnectionLiveTest") +public class PCSBlobStoreLiveTest { + + private PCSBlobStore connection; + + @BeforeGroups(groups = { "live" }) + public void setupConnection() { + String user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user"); + String password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key"); + URI endpoint = URI.create(checkNotNull(System.getProperty("jclouds.test.endpoint"), + "jclouds.test.endpoint")); + + connection = PCSContextFactory.createContext(endpoint, user, password, + new Log4JLoggingModule()).getApi(); + + } + + private String containerPrefix = BaseBlobStoreIntegrationTest.CONTAINER_PREFIX; + + @Test + public void testListContainers() throws Exception { + List response = connection.listContainers(); + assertNotNull(response); + long initialContainerCount = response.size(); + assertTrue(initialContainerCount >= 0); + + // Create test containers + String[] containerJsr330 = new String[] { containerPrefix + ".testListOwnedContainers1", + containerPrefix + ".testListOwnedContainers2" }; + assertTrue(connection.createContainer(containerJsr330[0]).get(10, TimeUnit.SECONDS)); + assertTrue(connection.createContainer(containerJsr330[1]).get(10, TimeUnit.SECONDS)); + assertTrue(connection.containerExists(containerJsr330[1])); + + // Test default listing + response = connection.listContainers(); + // Map nameToId = Maps.newHashMap(); + // + // for (ContainerMetadata data : response) { + // String path = data.getUrl().getPath(); + // int indexAfterContainersSlash = path.indexOf("containers/") + "containers/".length(); + // String id = path.substring(indexAfterContainersSlash); + // nameToId.put(data.getName(), id); + // } + // assert nameToId.size() >= 2 : nameToId; + // assertEquals(response.size(), initialContainerCount + 2);// if the containers already + // exist, this will fail + + // Cleanup and test containers have been removed + // assertTrue(connection.deleteContainer(nameToId.get(containerJsr330[0])).get(10, + // TimeUnit.SECONDS)); + // assertTrue(connection.deleteContainer(nameToId.get(containerJsr330[1])).get(10, + // TimeUnit.SECONDS)); + connection.listBlobs(containerJsr330[0]).get(10, TimeUnit.SECONDS); + connection.listBlobs(containerJsr330[1]).get(10, TimeUnit.SECONDS); + assertTrue(connection.deleteContainer(containerJsr330[0]).get(10, TimeUnit.SECONDS)); + assertTrue(connection.deleteContainer(containerJsr330[1]).get(10, TimeUnit.SECONDS)); + assertTrue(!connection.containerExists(containerJsr330[0])); + + response = connection.listContainers(); + // assertEquals(response.size(), initialContainerCount + 2);// if the containers already + // exist, this will fail + } + + @Test + public void testObjectOperations() throws Exception { + String containerName = containerPrefix + ".testObjectOperations"; + String data = "Here is my data"; + + assertTrue(connection.createContainer(containerName).get(10, TimeUnit.SECONDS)); + + // Test PUT with string data, ETag hash, and a piece of metadata + PCSFile object = new PCSFile("object"); + object.setData(data); + object.setContentLength(data.length()); + object.generateMD5(); + object.getMetadata().setContentType("text/plain"); + object.getMetadata().getUserMetadata().put("Metadata", "metadata-value"); + byte[] md5 = object.getMetadata().getContentMD5(); + // etag support by end of the year + assertNotNull(connection.putBlob(containerName, object).get(10, TimeUnit.SECONDS)); + assertEquals(HttpUtils.toHexString(md5), HttpUtils.toHexString(object.getMetadata() + .getContentMD5())); + + // Test HEAD of missing object + try { + connection.blobMetadata(containerName, "non-existent-object"); + assert false; + } catch (KeyNotFoundException e) { + } + + // Test HEAD of object + FileMetadata metadata = connection.blobMetadata(containerName, object.getKey()); + // TODO assertEquals(metadata.getKey(), object.getKey()); + assertEquals(metadata.getSize(), data.length()); + assertEquals(metadata.getContentType(), "text/plain"); + // assertEquals(HttpUtils.toHexString(md5), HttpUtils.toHexString(object.getMetadata() + // .getContentMD5())); + // assertEquals(metadata.getETag(), newEtag); + assertEquals(metadata.getUserMetadata().entries().size(), 1); + assertEquals(Iterables.getLast(metadata.getUserMetadata().get("metadata")), "metadata-value"); + + // // Test POST to update object's metadata + // Multimap userMetadata = HashMultimap.create(); + // userMetadata.put("New-Metadata-1", "value-1"); + // userMetadata.put("New-Metadata-2", "value-2"); + // assertTrue(connection.setObjectMetadata(containerName, object.getKey(), userMetadata)); + + // Test GET of missing object + try { + connection.getBlob(containerName, "non-existent-object").get(10, TimeUnit.SECONDS); + assert false; + } catch (KeyNotFoundException e) { + } + // Test GET of object (including updated metadata) + PCSFile getBlob = connection.getBlob(containerName, object.getKey()).get(120, + TimeUnit.SECONDS); + assertEquals(IOUtils.toString((InputStream) getBlob.getData()), data); + assertEquals(getBlob.getKey(), object.getKey()); + assertEquals(getBlob.getContentLength(), data.length()); + assertEquals(getBlob.getMetadata().getContentType(), "text/plain"); + // assertEquals(HttpUtils.toHexString(md5), HttpUtils.toHexString(getBlob.getMetadata() + // .getContentMD5())); + // assertEquals(newEtag, getBlob.getMetadata().getETag()); + // assertEquals(getBlob.getMetadata().getUserMetadata().entries().size(), 2); + // assertEquals( + // Iterables.getLast(getBlob.getMetadata().getUserMetadata().get("new-metadata-1")), + // "value-1"); + // assertEquals( + // Iterables.getLast(getBlob.getMetadata().getUserMetadata().get("new-metadata-2")), + // "value-2"); + + // Test PUT with invalid ETag (as if object's data was corrupted in transit) + // String correctEtag = HttpUtils.toHexString(newEtag); + // String incorrectEtag = "0" + correctEtag.substring(1); + // object.getMetadata().setETag(HttpUtils.fromHexString(incorrectEtag)); + try { + connection.putBlob(containerName, object).get(10, TimeUnit.SECONDS); + } catch (Throwable e) { + assertEquals(e.getCause().getClass(), HttpResponseException.class); + assertEquals(((HttpResponseException) e.getCause()).getResponse().getStatusCode(), 422); + } + + assertTrue(connection.removeBlob(containerName, "object").get(10, TimeUnit.SECONDS)); + assertTrue(connection.removeBlob(containerName, "chunked-object").get(10, TimeUnit.SECONDS)); + + assertTrue(connection.deleteContainer(containerName).get(10, TimeUnit.SECONDS)); + } + +} diff --git a/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/PCSBlobStoreTest.java b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/PCSBlobStoreTest.java new file mode 100644 index 0000000000..2fb5727c66 --- /dev/null +++ b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/PCSBlobStoreTest.java @@ -0,0 +1,448 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.Method; +import java.net.URI; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +import javax.inject.Named; +import javax.inject.Singleton; +import javax.ws.rs.HttpMethod; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; + +import org.jclouds.blobstore.BlobStoreMapsModule; +import org.jclouds.blobstore.functions.ReturnTrueOnNotFoundOr404; +import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404; +import org.jclouds.blobstore.integration.internal.StubBlobStore; +import org.jclouds.concurrent.WithinThreadExecutorService; +import org.jclouds.concurrent.config.ExecutorServiceModule; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule; +import org.jclouds.http.filters.BasicAuthentication; +import org.jclouds.http.functions.ParseSax; +import org.jclouds.http.functions.ReturnFalseOn404; +import org.jclouds.http.functions.ReturnStringIf200; +import org.jclouds.http.functions.ReturnTrueIf2xx; +import org.jclouds.http.options.GetOptions; +import org.jclouds.mezeo.pcs2.binders.PCSFileAsMultipartFormBinderTest; +import org.jclouds.mezeo.pcs2.config.PCSContextModule; +import org.jclouds.mezeo.pcs2.domain.ContainerMetadata; +import org.jclouds.mezeo.pcs2.domain.FileMetadata; +import org.jclouds.mezeo.pcs2.domain.PCSFile; +import org.jclouds.mezeo.pcs2.endpoints.RootContainer; +import org.jclouds.mezeo.pcs2.functions.AddMetadataAndParseResourceIdIntoBytes; +import org.jclouds.mezeo.pcs2.functions.AssembleBlobFromContentAndMetadataCache; +import org.jclouds.mezeo.pcs2.functions.InvalidateContainerNameCacheAndReturnTrueIf2xx; +import org.jclouds.mezeo.pcs2.functions.InvalidatePCSKeyCacheAndReturnTrueIf2xx; +import org.jclouds.mezeo.pcs2.functions.ReturnFalseIfContainerNotFound; +import org.jclouds.mezeo.pcs2.functions.ReturnTrueIfContainerNotFound; +import org.jclouds.mezeo.pcs2.reference.PCSConstants; +import org.jclouds.rest.JaxrsAnnotationProcessor; +import org.jclouds.rest.config.JaxrsModule; +import org.jclouds.util.DateService; +import org.jclouds.util.Jsr330; +import org.jclouds.util.Utils; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.Provides; +import com.google.inject.TypeLiteral; +import com.google.inject.internal.ImmutableList; + +/** + * Tests behavior of {@code PCSConnection} + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "pcs2.PCSConnectionTest") +public class PCSBlobStoreTest { + public static final class StubPCSConnection implements PCSBlobStore { + DateService dateService = new DateService(); + + public Future createContainer(String container) { + return null; + } + + public Future deleteContainer(String containerName) { + return null; + } + + public Future> listBlobs(String containerName) { + return new StubBlobStore.FutureBase>() { + public List get() throws InterruptedException, ExecutionException { + + return ImmutableList + .of( + new FileMetadata( + "more", + URI + .create("https://pcsbeta.mezeo.net/v2/files/5C81DADC-AAEE-11DE-9D55-B39340AEFF3A"), + dateService.fromSeconds(1254005157), dateService + .fromSeconds(1254005158), dateService + .fromSeconds(1254005159), "adrian@jclouds.org", + false, false, 1, 254288, + MediaType.APPLICATION_OCTET_STREAM, true), + + new FileMetadata( + "testfile.txt", + URI + .create("https://pcsbeta.mezeo.net/v2/files/9E4C5AFA-A98B-11DE-8B4C-C3884B4A2DA3"), + dateService.fromSeconds(1254000180), dateService + .fromSeconds(1254000181), dateService + .fromSeconds(1254000182), "adrian@jclouds.org", + false, true, 3, 5, MediaType.TEXT_PLAIN, false)); + + } + }; + + } + + public List listContainers() { + return ImmutableList + .of(new ContainerMetadata( + "mycontainer", + URI + .create("https://pcsbeta.mezeo.net/v2/containers/7F143552-AAF5-11DE-BBB0-0BC388ED913B"), + dateService.fromSeconds(1254008225), + dateService.fromSeconds(1254008226), + dateService.fromSeconds(1254008227), "adrian@jclouds.org", true, false, + 1, 1024)); + } + + public Future putBlob(String containerName, PCSFile object) { + return null; + } + + public Future removeBlob(String container, String key) { + return null; + } + + public Future getBlob(String container, String key) { + return null; + } + + public FileMetadata blobMetadata(String container, String key) { + return null; + } + + public Future getBlob(String container, String key, GetOptions options) { + return null; + } + + public boolean containerExists(String containerName) { + return false; + } + + } + + public void testListContainers() throws SecurityException, NoSuchMethodException { + Method method = PCSBlobStore.class.getMethod("listContainers"); + + HttpRequest httpMethod = processor.createRequest(method, new Object[] {}); + assertEquals(httpMethod.getEndpoint().getHost(), "localhost"); + assertEquals(httpMethod.getEndpoint().getPath(), "/root/contents"); + assertEquals(httpMethod.getEndpoint().getQuery(), null); + assertEquals(httpMethod.getMethod(), HttpMethod.GET); + assertEquals(httpMethod.getHeaders().size(), 1); + assertEquals(httpMethod.getHeaders().get("X-Cloud-Depth"), Collections.singletonList("2")); + assertEquals(processor.createResponseParser(method, httpMethod, null).getClass(), + ParseSax.class); + // TODO check generic type of response parser + assertEquals(processor.createExceptionParserOrNullIfNotFound(method), null); + } + + public void testCreateContainer() throws SecurityException, NoSuchMethodException, IOException { + Method method = PCSBlobStore.class.getMethod("createContainer", String.class); + + HttpRequest httpMethod = processor.createRequest(method, new Object[] { "container" }); + assertEquals(httpMethod.getEndpoint().getHost(), "localhost"); + assertEquals(httpMethod.getEndpoint().getPath(), "/root/contents"); + assertEquals(httpMethod.getEndpoint().getQuery(), null); + assertEquals(httpMethod.getMethod(), HttpMethod.POST); + assertEquals(httpMethod.getHeaders().size(), 2); + assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections + .singletonList("45")); + assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_TYPE), Collections + .singletonList("application/vnd.csp.container-info+xml")); + assertEquals(httpMethod.getEntity(), "container"); + assertEquals(processor.createResponseParser(method, httpMethod, null).getClass(), + ReturnTrueIf2xx.class); + // TODO check generic type of response parser + } + + public void testDeleteContainer() throws SecurityException, NoSuchMethodException { + Method method = PCSBlobStore.class.getMethod("deleteContainer", String.class); + + HttpRequest httpMethod = processor.createRequest(method, new Object[] { "mycontainer" }); + assertEquals(httpMethod.getEndpoint().getHost(), "localhost"); + assertEquals(httpMethod.getEndpoint().getPath(), + "/containers/7F143552-AAF5-11DE-BBB0-0BC388ED913B"); + assertEquals(httpMethod.getEndpoint().getQuery(), null); + assertEquals(httpMethod.getMethod(), HttpMethod.DELETE); + assertEquals(httpMethod.getHeaders().size(), 0); + assertEquals(processor.createResponseParser(method, httpMethod, null).getClass(), + InvalidateContainerNameCacheAndReturnTrueIf2xx.class); + assertEquals(processor.createExceptionParserOrNullIfNotFound(method).getClass(), + ReturnTrueIfContainerNotFound.class); + } + + public void testContainerExists() throws SecurityException, NoSuchMethodException { + Method method = PCSBlobStore.class.getMethod("containerExists", String.class); + + HttpRequest httpMethod = processor.createRequest(method, new Object[] { "mycontainer" }); + assertEquals(httpMethod.getEndpoint().getHost(), "localhost"); + assertEquals(httpMethod.getEndpoint().getPath(), + "/containers/7F143552-AAF5-11DE-BBB0-0BC388ED913B"); + assertEquals(httpMethod.getEndpoint().getQuery(), null); + assertEquals(httpMethod.getMethod(), HttpMethod.GET); + assertEquals(httpMethod.getHeaders().size(), 0); + assertEquals(processor.createResponseParser(method, httpMethod, null).getClass(), + ReturnTrueIf2xx.class); + assertEquals(processor.createExceptionParserOrNullIfNotFound(method).getClass(), + ReturnFalseIfContainerNotFound.class); + } + + public void testListBlobs() throws SecurityException, NoSuchMethodException { + Method method = PCSBlobStore.class.getMethod("listBlobs", String.class); + + HttpRequest httpMethod = processor.createRequest(method, new Object[] { "mycontainer" }); + assertEquals(httpMethod.getEndpoint().getHost(), "localhost"); + assertEquals(httpMethod.getEndpoint().getPath(), + "/containers/7F143552-AAF5-11DE-BBB0-0BC388ED913B/contents"); + assertEquals(httpMethod.getEndpoint().getQuery(), null); + assertEquals(httpMethod.getMethod(), HttpMethod.GET); + assertEquals(httpMethod.getHeaders().size(), 1); + assertEquals(httpMethod.getHeaders().get("X-Cloud-Depth"), Collections.singletonList("2")); + assertEquals(processor.createResponseParser(method, httpMethod, null).getClass(), + ParseSax.class); + // TODO check generic type of response parser + assertEquals(processor.createExceptionParserOrNullIfNotFound(method), null); + } + + public void testPutBlob() throws SecurityException, NoSuchMethodException, IOException { + Method method = PCSBlobStore.class.getMethod("putBlob", String.class, PCSFile.class); + + HttpRequest httpMethod = processor.createRequest(method, new Object[] { "mycontainer", + PCSFileAsMultipartFormBinderTest.TEST_BLOB }); + assertEquals(httpMethod.getEndpoint().getHost(), "localhost"); + assertEquals(httpMethod.getEndpoint().getPath(), + "/containers/7F143552-AAF5-11DE-BBB0-0BC388ED913B/contents"); + assertEquals(httpMethod.getEndpoint().getQuery(), null); + assertEquals(httpMethod.getMethod(), HttpMethod.POST); + assertEquals(httpMethod.getHeaders().size(), 2); + assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections + .singletonList(PCSFileAsMultipartFormBinderTest.EXPECTS.length() + "")); + assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_TYPE), Collections + .singletonList("multipart/form-data; boundary=" + + PCSFileAsMultipartFormBinderTest.BOUNDRY)); + assertEquals(Utils.toStringAndClose((InputStream) httpMethod.getEntity()), + PCSFileAsMultipartFormBinderTest.EXPECTS); + assertEquals(processor.createResponseParser(method, httpMethod, null).getClass(), + AddMetadataAndParseResourceIdIntoBytes.class); + } + + public void testRemoveBlob() throws SecurityException, NoSuchMethodException, IOException { + Method method = PCSBlobStore.class.getMethod("removeBlob", String.class, String.class); + + HttpRequest httpMethod = processor.createRequest(method, new Object[] { "mycontainer", + "testfile.txt" }); + assertEquals(httpMethod.getEndpoint().getHost(), "localhost"); + assertEquals(httpMethod.getEndpoint().getPath(), + "/files/9E4C5AFA-A98B-11DE-8B4C-C3884B4A2DA3"); + assertEquals(httpMethod.getEndpoint().getQuery(), null); + assertEquals(httpMethod.getMethod(), HttpMethod.DELETE); + assertEquals(httpMethod.getHeaders().size(), 0); + assertEquals(processor.createResponseParser(method, httpMethod, null).getClass(), + InvalidatePCSKeyCacheAndReturnTrueIf2xx.class); + assertEquals(processor.createExceptionParserOrNullIfNotFound(method).getClass(), + ReturnTrueOnNotFoundOr404.class); + } + + public void testGetBlob() throws SecurityException, NoSuchMethodException, IOException { + Method method = PCSBlobStore.class.getMethod("getBlob", String.class, String.class); + + HttpRequest httpMethod = processor.createRequest(method, new Object[] { "mycontainer", + "testfile.txt" }); + assertEquals(httpMethod.getEndpoint().getHost(), "localhost"); + assertEquals(httpMethod.getEndpoint().getPath(), + "/files/9E4C5AFA-A98B-11DE-8B4C-C3884B4A2DA3/content"); + assertEquals(httpMethod.getEndpoint().getQuery(), null); + assertEquals(httpMethod.getMethod(), HttpMethod.GET); + assertEquals(httpMethod.getHeaders().size(), 0); + assertEquals(processor.createResponseParser(method, httpMethod, null).getClass(), + AssembleBlobFromContentAndMetadataCache.class); + assertEquals(processor.createExceptionParserOrNullIfNotFound(method).getClass(), + ThrowKeyNotFoundOn404.class); + } + + public void testGetBlobOptios() throws SecurityException, NoSuchMethodException, IOException { + Method method = PCSBlobStore.class.getMethod("getBlob", String.class, String.class, + GetOptions.class); + + HttpRequest httpMethod = processor.createRequest(method, new Object[] { "mycontainer", + "testfile.txt", new GetOptions() }); + assertEquals(httpMethod.getEndpoint().getHost(), "localhost"); + assertEquals(httpMethod.getEndpoint().getPath(), + "/files/9E4C5AFA-A98B-11DE-8B4C-C3884B4A2DA3/content"); + assertEquals(httpMethod.getEndpoint().getQuery(), null); + assertEquals(httpMethod.getMethod(), HttpMethod.GET); + assertEquals(httpMethod.getHeaders().size(), 0); + assertEquals(processor.createResponseParser(method, httpMethod, null).getClass(), + AssembleBlobFromContentAndMetadataCache.class); + assertEquals(processor.createExceptionParserOrNullIfNotFound(method).getClass(), + ThrowKeyNotFoundOn404.class); + } + + public void testGetBlobMetadata() throws SecurityException, NoSuchMethodException, IOException { + Method method = PCSBlobStore.class.getMethod("blobMetadata", String.class, String.class); + + HttpRequest httpMethod = processor.createRequest(method, new Object[] { "mycontainer", + "testfile.txt" }); + assertEquals(httpMethod.getEndpoint().getHost(), "localhost"); + assertEquals(httpMethod.getEndpoint().getPath(), + "/files/9E4C5AFA-A98B-11DE-8B4C-C3884B4A2DA3"); + assertEquals(httpMethod.getEndpoint().getQuery(), null); + assertEquals(httpMethod.getMethod(), HttpMethod.GET); + assertEquals(processor.createResponseParser(method, httpMethod, null).getClass(), + ParseSax.class); + assertEquals(httpMethod.getHeaders().size(), 1); + assertEquals(httpMethod.getHeaders().get("X-Cloud-Depth"), Collections.singletonList("2")); + // TODO check generic type of response parser + assertEquals(processor.createExceptionParserOrNullIfNotFound(method).getClass(), + ThrowKeyNotFoundOn404.class); + } + + public void testPutMetadata() throws SecurityException, NoSuchMethodException { + Method method = PCSUtil.class.getMethod("put", URI.class, String.class); + HttpRequest httpMethod = utilProcessor.createRequest(method, new Object[] { + URI.create("http://localhost/pow"), "bar" }); + assertEquals(httpMethod.getEndpoint().getHost(), "localhost"); + assertEquals(httpMethod.getEndpoint().getPath(), "/pow"); + assertEquals(httpMethod.getMethod(), HttpMethod.PUT); + assertEquals(httpMethod.getHeaders().size(), 2); + assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections + .singletonList(httpMethod.getEntity().toString().getBytes().length + "")); + assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_TYPE), Collections + .singletonList("application/unknown")); + assertEquals("bar", httpMethod.getEntity()); + assertEquals(processor.createExceptionParserOrNullIfNotFound(method).getClass(), + ReturnFalseOn404.class); + assertEquals(processor.createResponseParser(method, httpMethod, null).getClass(), + ReturnTrueIf2xx.class); + } + + public void testGetMetadata() throws SecurityException, NoSuchMethodException { + Method method = PCSUtil.class.getMethod("get", URI.class); + + HttpRequest httpMethod = utilProcessor.createRequest(method, new Object[] { + URI.create("http://localhost/pow"), "foo" }); + assertEquals(httpMethod.getEndpoint().getHost(), "localhost"); + assertEquals(httpMethod.getEndpoint().getPath(), "/pow"); + assertEquals(httpMethod.getMethod(), HttpMethod.GET); + assertEquals(httpMethod.getHeaders().size(), 0); + assertEquals(processor.createExceptionParserOrNullIfNotFound(method), null); + assertEquals(processor.createResponseParser(method, httpMethod, null).getClass(), + ReturnStringIf200.class); + } + + JaxrsAnnotationProcessor processor; + private JaxrsAnnotationProcessor utilProcessor; + + @SuppressWarnings("unchecked") + @BeforeClass + void setupFactory() { + Injector injector = Guice.createInjector(new AbstractModule() { + @Override + protected void configure() { + bind(URI.class).annotatedWith(PCS.class) + .toInstance(URI.create("http://localhost:8080")); + bind(URI.class).annotatedWith(RootContainer.class).toInstance( + URI.create("http://localhost:8080/root")); + bindConstant().annotatedWith(Jsr330.named(PCSConstants.PROPERTY_PCS2_USER)).to("user"); + bindConstant().annotatedWith(Jsr330.named(PCSConstants.PROPERTY_PCS2_PASSWORD)).to( + "password"); + } + + @SuppressWarnings("unused") + @Provides + @Singleton + public PCSBlobStore getPCSConnection() { + return new StubPCSConnection(); + } + + @SuppressWarnings("unused") + @Provides + @Singleton + public PCSUtil getPCSUtil() { + return new PCSUtil() { + + public String get(URI resource) { + return null; + } + + public boolean put(URI resource, String value) { + return true; + } + + }; + } + + @SuppressWarnings("unused") + @Provides + @Singleton + public BasicAuthentication provideBasicAuthentication( + @Named(PCSConstants.PROPERTY_PCS2_USER) String user, + @Named(PCSConstants.PROPERTY_PCS2_PASSWORD) String password) + throws UnsupportedEncodingException { + return new BasicAuthentication(user, password); + } + }, new JaxrsModule(), new BlobStoreMapsModule(new TypeLiteral() { + }, new TypeLiteral() { + }, new TypeLiteral() { + }, new TypeLiteral() { + }), new PCSContextModule(), new ExecutorServiceModule(new WithinThreadExecutorService()), + new JavaUrlHttpCommandExecutorServiceModule()); + + processor = injector.getInstance(Key + .get(new TypeLiteral>() { + })); + utilProcessor = injector.getInstance(Key + .get(new TypeLiteral>() { + })); + } +} diff --git a/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/PCSCloudLiveTest.java b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/PCSCloudLiveTest.java index deca01a76e..4b824afd90 100644 --- a/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/PCSCloudLiveTest.java +++ b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/PCSCloudLiveTest.java @@ -1,5 +1,29 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2; +import static com.google.common.base.Preconditions.checkNotNull; import static org.testng.Assert.assertNotNull; import java.io.UnsupportedEncodingException; @@ -30,8 +54,10 @@ import com.google.inject.Provides; @Test(groups = "live", testName = "pcs2.PCSCloudLiveTest") public class PCSCloudLiveTest { - String user = System.getProperty("jclouds.test.user"); - String password = System.getProperty("jclouds.test.key"); + String user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user"); + String password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key"); + URI endpoint = URI.create(checkNotNull(System.getProperty("jclouds.test.endpoint"), + "jclouds.test.endpoint")); private Injector injector; @@ -54,8 +80,7 @@ public class PCSCloudLiveTest { injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { - bind(URI.class).annotatedWith(PCS.class).toInstance( - URI.create("https://pcsbeta.mezeo.net/v2")); + bind(URI.class).annotatedWith(PCS.class).toInstance(endpoint); } @SuppressWarnings("unused") diff --git a/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/PCSContextBuilderTest.java b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/PCSContextBuilderTest.java new file mode 100644 index 0000000000..8a76d9c076 --- /dev/null +++ b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/PCSContextBuilderTest.java @@ -0,0 +1,93 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2; + +import static org.testng.Assert.assertEquals; + +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + +import org.jclouds.cloud.CloudContext; +import org.jclouds.http.filters.BasicAuthentication; +import org.jclouds.mezeo.pcs2.config.RestPCSBlobStoreModule; +import org.jclouds.mezeo.pcs2.config.PCSContextModule.PCSContextImpl; +import org.jclouds.mezeo.pcs2.reference.PCSConstants; +import org.testng.annotations.Test; + +import com.google.inject.Injector; +import com.google.inject.Module; + +/** + * Tests behavior of modules configured in PCSContextBuilder + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "cloudfiles.PCSContextBuilderTest") +public class PCSContextBuilderTest { + + public void testNewBuilder() { + PCSContextBuilder builder = new PCSContextBuilder(URI.create("https://localhost:8080"), "id", + "secret"); + assertEquals(builder.getProperties().getProperty(PCSConstants.PROPERTY_PCS2_ENDPOINT), + "https://localhost:8080"); + assertEquals(builder.getProperties().getProperty(PCSConstants.PROPERTY_PCS2_USER), "id"); + assertEquals(builder.getProperties().getProperty(PCSConstants.PROPERTY_PCS2_PASSWORD), + "secret"); + } + + public void testBuildContext() { + CloudContext context = new PCSContextBuilder(URI + .create("https://localhost:8080"), "id", "secret").buildContext(); + assertEquals(context.getClass(), PCSContextImpl.class); + assertEquals(context.getAccount(), "id"); + assertEquals(context.getEndPoint(), URI.create("https://localhost:8080")); + } + + public void testBuildInjector() { + Injector i = new PCSContextBuilder(URI.create("https://localhost:8080"), "id", "secret") + .buildInjector(); + assert i.getInstance(PCSContext.class) != null; + assert i.getInstance(BasicAuthentication.class) != null; + } + + protected void testAddContextModule() { + List modules = new ArrayList(); + PCSContextBuilder builder = new PCSContextBuilder(URI.create("https://localhost:8080"), "id", + "secret"); + builder.addContextModule(modules); + assertEquals(modules.size(), 1); + assertEquals(modules.get(0).getClass(), RestPCSBlobStoreModule.class); + } + + protected void addConnectionModule() { + List modules = new ArrayList(); + PCSContextBuilder builder = new PCSContextBuilder(URI.create("https://localhost:8080"), "id", + "secret"); + builder.addConnectionModule(modules); + assertEquals(modules.size(), 1); + assertEquals(modules.get(0).getClass(), RestPCSBlobStoreModule.class); + } + +} diff --git a/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/binders/CreateContainerBinderTest.java b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/binders/CreateContainerBinderTest.java new file mode 100644 index 0000000000..898af16861 --- /dev/null +++ b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/binders/CreateContainerBinderTest.java @@ -0,0 +1,54 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.binders; + +import static org.testng.Assert.assertEquals; + +import java.net.URI; + +import javax.ws.rs.core.HttpHeaders; + +import org.jclouds.http.HttpRequest; +import org.testng.annotations.Test; + +/** + * Tests behavior of {@code ParseFlavorListFromGsonResponseTest} + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "pcs2.CreateContainerBinderTest") +public class CreateContainerBinderTest { + + public void test() { + CreateContainerBinder binder = new CreateContainerBinder(); + HttpRequest request = new HttpRequest("GET", URI.create("http://localhost")); + binder.addEntityToRequest("foo", request); + assertEquals(request.getEntity(), "foo"); + assertEquals(request.getFirstHeaderOrNull(HttpHeaders.CONTENT_LENGTH), + "foo".getBytes().length + ""); + assertEquals(request.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE), + "application/vnd.csp.container-info+xml"); + + } +} diff --git a/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/binders/PCSFileAsMultipartFormBinderTest.java b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/binders/PCSFileAsMultipartFormBinderTest.java new file mode 100644 index 0000000000..bd93404a7f --- /dev/null +++ b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/binders/PCSFileAsMultipartFormBinderTest.java @@ -0,0 +1,87 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.binders; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; + +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; + +import org.jclouds.http.HttpRequest; +import org.jclouds.mezeo.pcs2.domain.PCSFile; +import org.jclouds.util.Utils; +import org.testng.annotations.Test; + +/** + * Tests parsing of a request + * + * @author Adrian Cole + */ +@Test(testName = "pcs2.PCSFileAsMultipartFormBinderTest") +public class PCSFileAsMultipartFormBinderTest { + + public static String BOUNDRY = PCSFileAsMultipartFormBinder.BOUNDARY; + public static final String EXPECTS; + public static final PCSFile TEST_BLOB; + + static { + StringBuilder builder = new StringBuilder("--"); + addData(BOUNDRY, "hello", builder); + builder.append("--").append(BOUNDRY).append("--").append("\r\n"); + EXPECTS = builder.toString(); + TEST_BLOB = new PCSFile("hello"); + TEST_BLOB.setData("hello"); + TEST_BLOB.getMetadata().setContentType(MediaType.TEXT_PLAIN); + } + + public void testSinglePart() throws IOException { + + assertEquals(EXPECTS.length(), 123); + + PCSFileAsMultipartFormBinder binder = new PCSFileAsMultipartFormBinder(); + + HttpRequest request = new HttpRequest("GET", URI.create("http://localhost:8001")); + binder.addEntityToRequest(TEST_BLOB, request); + + assertEquals(Utils.toStringAndClose((InputStream) request.getEntity()), EXPECTS); + assertEquals(request.getFirstHeaderOrNull(HttpHeaders.CONTENT_LENGTH), 123 + ""); + + assertEquals(request.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE), + "multipart/form-data; boundary=" + BOUNDRY); + } + + private static void addData(String boundary, String data, StringBuilder builder) { + builder.append(boundary).append("\r\n"); + builder.append("Content-Disposition").append(": ").append( + "form-data; name=\"hello\"; filename=\"hello\"").append("\r\n"); + builder.append("Content-Type").append(": ").append("text/plain").append("\r\n"); + builder.append("\r\n"); + builder.append(data).append("\r\n"); + } + +} diff --git a/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/config/PCSContextModuleTest.java b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/config/PCSContextModuleTest.java new file mode 100644 index 0000000000..bdd5320dfb --- /dev/null +++ b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/config/PCSContextModuleTest.java @@ -0,0 +1,84 @@ +package org.jclouds.mezeo.pcs2.config; + +import static org.testng.Assert.assertEquals; + +import org.jclouds.blobstore.BlobStoreMapsModule; +import org.jclouds.concurrent.WithinThreadExecutorService; +import org.jclouds.concurrent.config.ExecutorServiceModule; +import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule; +import org.jclouds.http.functions.config.ParserModule; +import org.jclouds.http.handlers.CloseContentAndSetExceptionErrorHandler; +import org.jclouds.http.handlers.DelegatingErrorHandler; +import org.jclouds.http.handlers.DelegatingRetryHandler; +import org.jclouds.http.handlers.RedirectionRetryHandler; +import org.jclouds.mezeo.pcs2.PCSBlobStore; +import org.jclouds.mezeo.pcs2.domain.ContainerMetadata; +import org.jclouds.mezeo.pcs2.domain.FileMetadata; +import org.jclouds.mezeo.pcs2.domain.PCSFile; +import org.jclouds.mezeo.pcs2.handlers.PCSClientErrorRetryHandler; +import org.jclouds.mezeo.pcs2.reference.PCSConstants; +import org.jclouds.util.Jsr330; +import org.testng.annotations.Test; + +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.TypeLiteral; + +/** + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "pcs2.PCSContextModuleTest") +public class PCSContextModuleTest { + + Injector createInjector() { + return Guice.createInjector(new RestPCSBlobStoreModule(), + new BlobStoreMapsModule( + new TypeLiteral() { + }, new TypeLiteral() { + }, new TypeLiteral() { + }, new TypeLiteral() { + }), new PCSContextModule() { + @Override + protected void configure() { + bindConstant().annotatedWith(Jsr330.named(PCSConstants.PROPERTY_PCS2_USER)) + .to("user"); + bindConstant() + .annotatedWith(Jsr330.named(PCSConstants.PROPERTY_PCS2_PASSWORD)).to( + "key"); + bindConstant() + .annotatedWith(Jsr330.named(PCSConstants.PROPERTY_PCS2_ENDPOINT)).to( + "http://localhost"); + super.configure(); + } + }, new ParserModule(), new JavaUrlHttpCommandExecutorServiceModule(), + new ExecutorServiceModule(new WithinThreadExecutorService())); + } + + @Test + void testServerErrorHandler() { + DelegatingErrorHandler handler = createInjector().getInstance(DelegatingErrorHandler.class); + assertEquals(handler.getServerErrorHandler().getClass(), + CloseContentAndSetExceptionErrorHandler.class); + } + + @Test + void testClientErrorHandler() { + DelegatingErrorHandler handler = createInjector().getInstance(DelegatingErrorHandler.class); + assertEquals(handler.getClientErrorHandler().getClass(), + CloseContentAndSetExceptionErrorHandler.class); + } + + @Test + void testClientRetryHandler() { + DelegatingRetryHandler handler = createInjector().getInstance(DelegatingRetryHandler.class); + assertEquals(handler.getClientErrorRetryHandler().getClass(), + PCSClientErrorRetryHandler.class); + } + + @Test + void testRedirectionRetryHandler() { + DelegatingRetryHandler handler = createInjector().getInstance(DelegatingRetryHandler.class); + assertEquals(handler.getRedirectionRetryHandler().getClass(), RedirectionRetryHandler.class); + } + +} \ No newline at end of file diff --git a/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/config/StubPCSBlobStoreModule.java b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/config/StubPCSBlobStoreModule.java new file mode 100644 index 0000000000..340064d2dc --- /dev/null +++ b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/config/StubPCSBlobStoreModule.java @@ -0,0 +1,58 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.config; + +import java.net.URI; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.jclouds.cloud.ConfiguresCloudConnection; +import org.jclouds.http.functions.config.ParserModule; +import org.jclouds.mezeo.pcs2.PCS; +import org.jclouds.mezeo.pcs2.PCSBlobStore; +import org.jclouds.mezeo.pcs2.domain.PCSFile; +import org.jclouds.mezeo.pcs2.internal.StubPCSBlobStore; + +import com.google.inject.AbstractModule; +import com.google.inject.TypeLiteral; + +/** + * adds a stub alternative to invoking PCSBlob + * + * @author Adrian Cole + */ +@ConfiguresCloudConnection +public class StubPCSBlobStoreModule extends AbstractModule { + + static final ConcurrentHashMap> map = new ConcurrentHashMap>(); + + protected void configure() { + install(new ParserModule()); + bind(new TypeLiteral>>() { + }).toInstance(map); + bind(PCSBlobStore.class).to(StubPCSBlobStore.class).asEagerSingleton(); + bind(URI.class).annotatedWith(PCS.class).toInstance(URI.create("https://localhost/pcsblob")); + } + +} \ No newline at end of file diff --git a/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/functions/AddMetadataAndParseResourceIdIntoBytesTest.java b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/functions/AddMetadataAndParseResourceIdIntoBytesTest.java new file mode 100644 index 0000000000..97bb97ea1b --- /dev/null +++ b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/functions/AddMetadataAndParseResourceIdIntoBytesTest.java @@ -0,0 +1,125 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.functions; + +import static org.easymock.EasyMock.eq; +import static org.easymock.EasyMock.expect; +import static org.easymock.classextension.EasyMock.createMock; +import static org.easymock.classextension.EasyMock.replay; +import static org.easymock.classextension.EasyMock.verify; +import static org.testng.Assert.assertEquals; + +import java.net.URI; + +import javax.ws.rs.ext.RuntimeDelegate; + +import org.apache.commons.io.IOUtils; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.HttpUtils; +import org.jclouds.mezeo.pcs2.PCSUtil; +import org.jclouds.mezeo.pcs2.domain.PCSFile; +import org.jclouds.rest.RuntimeDelegateImpl; +import org.testng.annotations.Test; + +/** + * Tests behavior of {@code UseResourceIdAsETag} + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "pcs2.AddMetadataAndParseResourceIdIntoBytesTest") +public class AddMetadataAndParseResourceIdIntoBytesTest { + static { + RuntimeDelegate.setInstance(new RuntimeDelegateImpl()); + } + HttpResponse response = new HttpResponse(); + + PCSUtil createPCSUtil() { + PCSUtil connection = createMock(PCSUtil.class); + expect( + connection + .put( + eq(URI + .create("http://localhost/contents/7F143552-AAF5-11DE-BBB0-0BC388ED913B/metadata/foo")), + eq("bar"))).andReturn(true); + expect( + connection + .put( + eq(URI + .create("http://localhost/contents/7F143552-AAF5-11DE-BBB0-0BC388ED913B/metadata/biz")), + eq("baz"))).andReturn(true); + replay(connection); + return connection; + } + + @Test(expectedExceptions = IllegalStateException.class) + public void testNoArgs() { + AddMetadataAndParseResourceIdIntoBytes function = new AddMetadataAndParseResourceIdIntoBytes( + createPCSUtil()); + + function.apply(response); + } + + @Test(expectedExceptions = IllegalStateException.class) + public void testNoRequest() { + AddMetadataAndParseResourceIdIntoBytes function = new AddMetadataAndParseResourceIdIntoBytes( + createPCSUtil()); + function.setContext(null, new Object[] { new PCSFile("key") }); + function.apply(response); + } + + public void testGetEtag() { + PCSUtil connection = createPCSUtil(); + AddMetadataAndParseResourceIdIntoBytes function = new AddMetadataAndParseResourceIdIntoBytes( + connection); + function.setContext(new HttpRequest("GET", URI.create("http://localhost:8080")), + new Object[] { new PCSFile("key") }); + response.setContent(IOUtils + .toInputStream("http://localhost/contents/7F143552-AAF5-11DE-BBB0-0BC388ED913B")); + byte[] eTag = function.apply(response); + + byte[] expected = HttpUtils.fromHexString("7F143552AAF511DEBBB00BC388ED913B"); + assertEquals(eTag, expected); + } + + public void testMetadataGetEtag() { + PCSUtil connection = createPCSUtil(); + AddMetadataAndParseResourceIdIntoBytes function = new AddMetadataAndParseResourceIdIntoBytes( + connection); + PCSFile pcsFile = new PCSFile("key"); + pcsFile.getMetadata().getUserMetadata().put("foo", "bar"); + pcsFile.getMetadata().getUserMetadata().put("biz", "baz"); + + function.setContext(new HttpRequest("GET", URI.create("http://localhost:8080")), + new Object[] { pcsFile }); + response.setContent(IOUtils + .toInputStream("http://localhost/contents/7F143552-AAF5-11DE-BBB0-0BC388ED913B")); + byte[] eTag = function.apply(response); + + byte[] expected = HttpUtils.fromHexString("7F143552AAF511DEBBB00BC388ED913B"); + assertEquals(eTag, expected); + verify(connection); + } + +} diff --git a/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/functions/AssembleBlobFromBlobMetadataCallTest.java b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/functions/AssembleBlobFromBlobMetadataCallTest.java new file mode 100644 index 0000000000..c418aed500 --- /dev/null +++ b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/functions/AssembleBlobFromBlobMetadataCallTest.java @@ -0,0 +1,66 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.functions; + +import static org.easymock.EasyMock.expect; +import static org.easymock.classextension.EasyMock.createMock; +import static org.easymock.classextension.EasyMock.replay; +import static org.testng.Assert.assertEquals; + +import java.io.InputStream; +import java.util.concurrent.ConcurrentMap; + +import org.jclouds.http.HttpException; +import org.jclouds.http.HttpResponse; +import org.jclouds.mezeo.pcs2.domain.FileMetadata; +import org.jclouds.mezeo.pcs2.domain.PCSFile; +import org.testng.annotations.Test; + +/** + * @author Adrian Cole + */ +public class AssembleBlobFromBlobMetadataCallTest { + + @SuppressWarnings("unchecked") + @Test(expectedExceptions = NullPointerException.class) + public void testCall() throws HttpException { + FileMetadata metadata = new FileMetadata("blob"); + metadata.setSize(103); + ConcurrentMap mdCache = createMock(ConcurrentMap.class); + InputStream data = createMock(InputStream.class); + AssembleBlobFromContentAndMetadataCache callable = new AssembleBlobFromContentAndMetadataCache( + mdCache); + HttpResponse response = createMock(HttpResponse.class); + expect(mdCache.get(new Key("container", "blob"))).andReturn(metadata); + expect(response.getContent()).andReturn(data); + replay(mdCache); + replay(response); + PCSFile file = callable.apply(response); + assertEquals(file.getMetadata(), metadata); + assertEquals(file.getKey(), "blob"); + assertEquals(file.getData(), data); + assertEquals(file.getContentLength(), metadata.getSize()); + } + +} diff --git a/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/functions/FindIdInContainerListTest.java b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/functions/FindIdInContainerListTest.java new file mode 100644 index 0000000000..ecc36198ed --- /dev/null +++ b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/functions/FindIdInContainerListTest.java @@ -0,0 +1,68 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.functions; + +import static org.easymock.classextension.EasyMock.createNiceMock; +import static org.testng.Assert.assertEquals; + +import java.net.URI; + +import org.jclouds.blobstore.ContainerNotFoundException; +import org.jclouds.mezeo.pcs2.PCSBlobStore; +import org.jclouds.mezeo.pcs2.domain.ContainerMetadata; +import org.jclouds.util.DateService; +import org.testng.annotations.Test; + +import com.google.inject.internal.ImmutableList; + +/** + * Tests behavior of {@code ContainerResourceId} + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "pcs2.FindIdInContainerList") +public class FindIdInContainerListTest { + private DateService dateService = new DateService(); + + private final ImmutableList OF = ImmutableList + .of(new ContainerMetadata( + "test1", + URI + .create("https://pcsbeta.mezeo.net/v2/containers/7F143552-AAF5-11DE-BBB0-0BC388ED913B"), + dateService.fromSeconds(1254008225), dateService.fromSeconds(1254008226), + dateService.fromSeconds(1254008227), "adrian@jclouds.org", true, false, 1, + 1024)); + + @Test(expectedExceptions = ContainerNotFoundException.class) + public void testBad() { + FindIdInContainerList binder = new FindIdInContainerList(createNiceMock(PCSBlobStore.class)); + binder.idForNameInListOrException("hello", OF); + } + + public void testGood() { + FindIdInContainerList binder = new FindIdInContainerList(createNiceMock(PCSBlobStore.class)); + assertEquals(binder.idForNameInListOrException("test1", OF), + "7F143552-AAF5-11DE-BBB0-0BC388ED913B"); + } +} diff --git a/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/functions/FindIdInFileListIdTest.java b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/functions/FindIdInFileListIdTest.java new file mode 100644 index 0000000000..463bfd65dc --- /dev/null +++ b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/functions/FindIdInFileListIdTest.java @@ -0,0 +1,73 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.functions; + +import static org.easymock.classextension.EasyMock.createNiceMock; +import static org.testng.Assert.assertEquals; + +import java.net.URI; + +import javax.ws.rs.core.MediaType; + +import org.jclouds.blobstore.KeyNotFoundException; +import org.jclouds.mezeo.pcs2.PCSBlobStore; +import org.jclouds.mezeo.pcs2.domain.FileMetadata; +import org.jclouds.util.DateService; +import org.testng.annotations.Test; + +import com.google.inject.internal.ImmutableList; + +/** + * Tests behavior of {@code ContainerResourceId} + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "pcs2.FindIdInFileListTest") +public class FindIdInFileListIdTest { + private DateService dateService = new DateService(); + + private final ImmutableList OF = ImmutableList.of(new FileMetadata("more", URI + .create("https://pcsbeta.mezeo.net/v2/files/5C81DADC-AAEE-11DE-9D55-B39340AEFF3A"), + dateService.fromSeconds(1254005157), dateService.fromSeconds(1254005158), dateService + .fromSeconds(1254005159), "adrian@jclouds.org", false, false, 1, 254288, + MediaType.APPLICATION_OCTET_STREAM, true), + + new FileMetadata("testfile.txt", URI + .create("https://pcsbeta.mezeo.net/v2/files/9E4C5AFA-A98B-11DE-8B4C-C3884B4A2DA3"), + dateService.fromSeconds(1254000180), dateService.fromSeconds(1254000181), dateService + .fromSeconds(1254000182), "adrian@jclouds.org", false, true, 3, 5, + MediaType.TEXT_PLAIN, false)); + + @Test(expectedExceptions = KeyNotFoundException.class) + public void testBad() { + FindIdInFileList binder = new FindIdInFileList(createNiceMock(PCSBlobStore.class)); + binder.idForNameInListOrException("bob", "hello", OF); + } + + public void testGood() { + FindIdInFileList binder = new FindIdInFileList(createNiceMock(PCSBlobStore.class)); + assertEquals(binder.idForNameInListOrException("bob", "testfile.txt", OF), + "9E4C5AFA-A98B-11DE-8B4C-C3884B4A2DA3"); + } +} diff --git a/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/integration/PCSBlobMapIntegrationTest.java b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/integration/PCSBlobMapIntegrationTest.java new file mode 100644 index 0000000000..9a83e54c79 --- /dev/null +++ b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/integration/PCSBlobMapIntegrationTest.java @@ -0,0 +1,47 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.integration; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; + +import org.jclouds.blobstore.integration.internal.BaseBlobMapIntegrationTest; +import org.jclouds.mezeo.pcs2.PCSBlobStore; +import org.jclouds.mezeo.pcs2.domain.ContainerMetadata; +import org.jclouds.mezeo.pcs2.domain.FileMetadata; +import org.jclouds.mezeo.pcs2.domain.PCSFile; +import org.testng.annotations.Test; + +/** + * @author Adrian Cole + */ +@Test(groups = { "integration", "live" }, testName = "cloudfiles.PCSBlobMapIntegrationTest") +public class PCSBlobMapIntegrationTest extends + BaseBlobMapIntegrationTest { + + @Override + public void testContains() throws InterruptedException, ExecutionException, TimeoutException { + // not supported + } +} \ No newline at end of file diff --git a/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/integration/PCSBlobStoreContainerIntegrationTest.java b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/integration/PCSBlobStoreContainerIntegrationTest.java new file mode 100755 index 0000000000..01602baac6 --- /dev/null +++ b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/integration/PCSBlobStoreContainerIntegrationTest.java @@ -0,0 +1,55 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.integration; + +import java.util.concurrent.TimeUnit; + +import org.jclouds.blobstore.integration.internal.BaseContainerIntegrationTest; +import org.jclouds.mezeo.pcs2.PCSBlobStore; +import org.jclouds.mezeo.pcs2.domain.ContainerMetadata; +import org.jclouds.mezeo.pcs2.domain.FileMetadata; +import org.jclouds.mezeo.pcs2.domain.PCSFile; +import org.testng.annotations.Test; + +/** + * @author Adrian Cole + */ +@Test(groups = { "integration", "live" }, testName = "cloudfiles.PCSBlobContainerIntegrationTest") +public class PCSBlobStoreContainerIntegrationTest extends + BaseContainerIntegrationTest { + + @Override + @Test(groups = { "integration", "live" }) + public void deleteContainerIfEmptyButHasContents() throws Exception { + String containerName = getContainerName(); + try { + addBlobToContainer(containerName, "test"); + // true is returned, since we can delete containers with contents + assert context.getApi().deleteContainer(containerName).get(10, TimeUnit.SECONDS); + } finally { + returnContainer(containerName); + } + } + +} \ No newline at end of file diff --git a/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/integration/PCSBlobStoreContainerLiveTest.java b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/integration/PCSBlobStoreContainerLiveTest.java new file mode 100644 index 0000000000..6cd601967d --- /dev/null +++ b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/integration/PCSBlobStoreContainerLiveTest.java @@ -0,0 +1,40 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.integration; + +import org.jclouds.blobstore.integration.internal.BaseContainerLiveTest; +import org.jclouds.mezeo.pcs2.PCSBlobStore; +import org.jclouds.mezeo.pcs2.domain.ContainerMetadata; +import org.jclouds.mezeo.pcs2.domain.FileMetadata; +import org.jclouds.mezeo.pcs2.domain.PCSFile; +import org.testng.annotations.Test; + +/** + * @author Adrian Cole + */ +@Test(groups = { "live" }, testName = "cloudfiles.PCSBlobContainerLiveTest") +public class PCSBlobStoreContainerLiveTest extends + BaseContainerLiveTest { + +} \ No newline at end of file diff --git a/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/integration/PCSBlobStoreIntegrationTest.java b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/integration/PCSBlobStoreIntegrationTest.java new file mode 100755 index 0000000000..ad39388493 --- /dev/null +++ b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/integration/PCSBlobStoreIntegrationTest.java @@ -0,0 +1,119 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.integration; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; +import java.util.Collections; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; + +import org.jclouds.blobstore.integration.internal.BaseBlobIntegrationTest; +import org.jclouds.mezeo.pcs2.PCSBlobStore; +import org.jclouds.mezeo.pcs2.domain.ContainerMetadata; +import org.jclouds.mezeo.pcs2.domain.FileMetadata; +import org.jclouds.mezeo.pcs2.domain.PCSFile; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +/** + * @author Adrian Cole + */ +@Test(groups = { "integration", "live" }, testName = "cloudfiles.PCSBlobIntegrationTest") +public class PCSBlobStoreIntegrationTest extends + BaseBlobIntegrationTest { + @Override + protected void validateMetadata(FileMetadata metadata) { + assertEquals(metadata.getContentType(), "text/plain"); + assertEquals(metadata.getSize(), TEST_STRING.length()); + assertEquals(metadata.getUserMetadata().get("adrian"), Collections + .singletonList("powderpuff")); + // Content-MD5 not supported http://code.google.com/p/jclouds/issues/detail?id=105 + // assertEquals(metadata.getContentMD5(), HttpUtils.md5(TEST_STRING.getBytes())); + } + + @Override + @Test(enabled = false) + public void testGetIfMatch() throws InterruptedException, ExecutionException, TimeoutException, + IOException { + // etag not supported http://code.google.com/p/jclouds/issues/detail?id=105 + } + + @Override + @Test(enabled = false) + public void testGetIfModifiedSince() throws InterruptedException, ExecutionException, + TimeoutException, IOException { + // unsupported + } + + @Override + @Test(enabled = false) + public void testGetIfNoneMatch() throws InterruptedException, ExecutionException, + TimeoutException, IOException { + // etag not supported http://code.google.com/p/jclouds/issues/detail?id=105 + } + + @Override + @Test(enabled = false) + public void testGetIfUnmodifiedSince() throws InterruptedException, ExecutionException, + TimeoutException, IOException { + // unsupported + } + + @Override + @Test(enabled = false) + public void testGetRange() throws InterruptedException, ExecutionException, TimeoutException, + IOException { + // unsupported http://code.google.com/p/jclouds/issues/detail?id=106 + } + + @Override + @Test(enabled = false) + public void testGetStartAt() throws InterruptedException, ExecutionException, TimeoutException, + IOException { + // unsupported http://code.google.com/p/jclouds/issues/detail?id=106 + } + + @Override + @Test(enabled = false) + public void testGetTail() throws InterruptedException, ExecutionException, TimeoutException, + IOException { + // unsupported http://code.google.com/p/jclouds/issues/detail?id=106 + } + + @Override + @Test(enabled = false) + public void testGetTwoRanges() throws InterruptedException, ExecutionException, + TimeoutException, IOException { + // unsupported http://code.google.com/p/jclouds/issues/detail?id=106 + } + + @DataProvider(name = "delete") + @Override + public Object[][] createData() { + return new Object[][] { { "normal" } }; + } + +} \ No newline at end of file diff --git a/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/integration/PCSBlobStoreLiveTest.java b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/integration/PCSBlobStoreLiveTest.java new file mode 100644 index 0000000000..67d6929e1f --- /dev/null +++ b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/integration/PCSBlobStoreLiveTest.java @@ -0,0 +1,46 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.integration; + +import org.jclouds.blobstore.integration.internal.BaseBlobLiveTest; +import org.jclouds.mezeo.pcs2.PCSBlobStore; +import org.jclouds.mezeo.pcs2.domain.ContainerMetadata; +import org.jclouds.mezeo.pcs2.domain.FileMetadata; +import org.jclouds.mezeo.pcs2.domain.PCSFile; +import org.testng.annotations.Test; + +/** + * @author Adrian Cole + */ +@Test(groups = { "live" }, testName = "cloudfiles.PCSBlobLiveTest") +public class PCSBlobStoreLiveTest extends + BaseBlobLiveTest { + + @Override + @Test(enabled = false) + public void testCopyUrl(String httpStreamUrl, String httpStreamETag) throws Exception { + // depends on md5 which is not yet supported + } + +} \ No newline at end of file diff --git a/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/integration/PCSBlobStoreServiceIntegrationTest.java b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/integration/PCSBlobStoreServiceIntegrationTest.java new file mode 100644 index 0000000000..877c8ae218 --- /dev/null +++ b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/integration/PCSBlobStoreServiceIntegrationTest.java @@ -0,0 +1,40 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.integration; + +import org.jclouds.blobstore.integration.internal.BaseServiceIntegrationTest; +import org.jclouds.mezeo.pcs2.PCSBlobStore; +import org.jclouds.mezeo.pcs2.domain.ContainerMetadata; +import org.jclouds.mezeo.pcs2.domain.FileMetadata; +import org.jclouds.mezeo.pcs2.domain.PCSFile; +import org.testng.annotations.Test; + +/** + * @author Adrian Cole + */ +@Test(groups = { "integration", "live" }, testName = "cloudfiles.PCSBlobServiceIntegrationTest") +public class PCSBlobStoreServiceIntegrationTest extends + BaseServiceIntegrationTest { + +} \ No newline at end of file diff --git a/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/integration/PCSInputStreamMapIntegrationTest.java b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/integration/PCSInputStreamMapIntegrationTest.java new file mode 100644 index 0000000000..6e966cbfb8 --- /dev/null +++ b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/integration/PCSInputStreamMapIntegrationTest.java @@ -0,0 +1,66 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.integration; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; + +import org.jclouds.blobstore.integration.internal.BaseInputStreamMapIntegrationTest; +import org.jclouds.mezeo.pcs2.PCSBlobStore; +import org.jclouds.mezeo.pcs2.domain.ContainerMetadata; +import org.jclouds.mezeo.pcs2.domain.FileMetadata; +import org.jclouds.mezeo.pcs2.domain.PCSFile; +import org.testng.annotations.Test; + +/** + * @author Adrian Cole + */ +@Test(groups = { "integration", "live" }, testName = "cloudfiles.PCSBlobInputStreamMapIntegrationTest") +public class PCSInputStreamMapIntegrationTest extends + BaseInputStreamMapIntegrationTest { + + @Override + public void testContainsBytesValue() throws InterruptedException, ExecutionException, + TimeoutException { + // not supported + } + + @Override + public void testContainsFileValue() throws InterruptedException, ExecutionException, + TimeoutException { + // not supported + } + + @Override + public void testContainsInputStreamValue() throws InterruptedException, ExecutionException, + TimeoutException { + // not supported + } + + @Override + public void testContainsStringValue() throws InterruptedException, ExecutionException, + TimeoutException { + // not supported + } +} \ No newline at end of file diff --git a/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/integration/PCSTestInitializer.java b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/integration/PCSTestInitializer.java new file mode 100644 index 0000000000..6852d37ede --- /dev/null +++ b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/integration/PCSTestInitializer.java @@ -0,0 +1,60 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.integration; + +import java.net.URI; + +import org.jclouds.blobstore.integration.internal.BaseTestInitializer; +import org.jclouds.logging.log4j.config.Log4JLoggingModule; +import org.jclouds.mezeo.pcs2.PCSBlobStore; +import org.jclouds.mezeo.pcs2.PCSContext; +import org.jclouds.mezeo.pcs2.PCSContextBuilder; +import org.jclouds.mezeo.pcs2.PCSContextFactory; +import org.jclouds.mezeo.pcs2.config.StubPCSBlobStoreModule; +import org.jclouds.mezeo.pcs2.domain.ContainerMetadata; +import org.jclouds.mezeo.pcs2.domain.FileMetadata; +import org.jclouds.mezeo.pcs2.domain.PCSFile; + +import com.google.inject.Module; + +/** + * + * @author Adrian Cole + */ +public class PCSTestInitializer extends + BaseTestInitializer { + + @Override + protected PCSContext createLiveContext(Module configurationModule, String url, String app, + String account, String key) { + return new PCSContextBuilder(URI.create(url), account, key).relaxSSLHostname().withModules( + configurationModule, new Log4JLoggingModule()).buildContext(); + } + + @Override + protected PCSContext createStubContext() { + return PCSContextFactory.createContext(URI.create("http://localhost/stubpcs"), "user", + "pass", new StubPCSBlobStoreModule()); + } +} \ No newline at end of file diff --git a/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/internal/StubPCSBlobStore.java b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/internal/StubPCSBlobStore.java new file mode 100644 index 0000000000..539c64218e --- /dev/null +++ b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/internal/StubPCSBlobStore.java @@ -0,0 +1,64 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.internal; + +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +import javax.inject.Inject; +import javax.inject.Provider; + +import org.jclouds.blobstore.integration.internal.StubBlobStore; +import org.jclouds.mezeo.pcs2.PCSBlobStore; +import org.jclouds.mezeo.pcs2.domain.ContainerMetadata; +import org.jclouds.mezeo.pcs2.domain.FileMetadata; +import org.jclouds.mezeo.pcs2.domain.PCSFile; +import org.jclouds.util.DateService; + +/** + * Implementation of {@link PCSBlobStore} which keeps all data in a local Map object. + * + * @author Adrian Cole + */ +public class StubPCSBlobStore extends StubBlobStore + implements PCSBlobStore { + + @Override + public Future deleteContainer(final String container) { + return new FutureBase() { + public Boolean get() throws InterruptedException, ExecutionException { + getContainerToBlobs().remove(container); + return true; + } + }; + } + + @Inject + protected StubPCSBlobStore(Map> containerToBlobs, + DateService dateService, Provider containerMetaProvider, + Provider blobProvider) { + super(containerToBlobs, dateService, containerMetaProvider, blobProvider); + } +} diff --git a/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/util/PCSUtilsTest.java b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/util/PCSUtilsTest.java new file mode 100644 index 0000000000..c0bf9f2056 --- /dev/null +++ b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/util/PCSUtilsTest.java @@ -0,0 +1,47 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.util; + +import static org.testng.Assert.assertEquals; + +import java.net.URI; + +import org.jclouds.http.HttpUtils; +import org.testng.annotations.Test; + +/** + * Tests behavior of {@code PCSUtils} + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "pcs2.PCSUtilsTest") +public class PCSUtilsTest { + public void testGetEtag() { + byte[] expected = HttpUtils.fromHexString("7F143552AAF511DEBBB00BC388ED913B"); + + byte[] eTag = PCSUtils.getEtag(URI + .create("http://localhost/contents/7F143552-AAF5-11DE-BBB0-0BC388ED913B")); + assertEquals(eTag, expected); + } +} diff --git a/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/xml/CloudXlinkHanderTest.java b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/xml/CloudXlinkHanderTest.java index 0d7d6cd43c..d2ebae7fdd 100644 --- a/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/xml/CloudXlinkHanderTest.java +++ b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/xml/CloudXlinkHanderTest.java @@ -1,3 +1,26 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.xml; import static org.testng.Assert.assertEquals; diff --git a/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/xml/FileListToContainerMetadataListHandlerTest.java b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/xml/FileListToContainerMetadataListHandlerTest.java new file mode 100644 index 0000000000..ae7885334a --- /dev/null +++ b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/xml/FileListToContainerMetadataListHandlerTest.java @@ -0,0 +1,75 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.xml; + +import static org.testng.Assert.assertEquals; + +import java.io.InputStream; +import java.net.URI; +import java.util.List; + +import org.jclouds.http.functions.BaseHandlerTest; +import org.jclouds.mezeo.pcs2.domain.ContainerMetadata; +import org.jclouds.util.DateService; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; + +/** + * Tests behavior of {@code FileListToContainerMetadataListHandler} + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "pcs2.FileListToContainerMetadataListHandlerTest") +public class FileListToContainerMetadataListHandlerTest extends BaseHandlerTest { + + private DateService dateService; + + @BeforeTest + @Override + protected void setUpInjector() { + super.setUpInjector(); + dateService = injector.getInstance(DateService.class); + assert dateService != null; + } + + @SuppressWarnings("unchecked") + public void testApplyInputStream() { + InputStream is = getClass().getResourceAsStream("/test_file_list.xml"); + List list = ImmutableList + .of(new ContainerMetadata( + "test1", + URI + .create("https://pcsbeta.mezeo.net/v2/containers/7F143552-AAF5-11DE-BBB0-0BC388ED913B"), + dateService.fromSeconds(1254008225), dateService.fromSeconds(1254008226), + dateService.fromSeconds(1254008227), "adrian@jclouds.org", true, false, 1, + 1024)); + + List result = (List) factory.create( + injector.getInstance(FileListToContainerMetadataListHandler.class)).parse(is); + + assertEquals(result, list); + } +} diff --git a/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/xml/FileListToFileMetadataListHandlerTest.java b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/xml/FileListToFileMetadataListHandlerTest.java new file mode 100644 index 0000000000..781a646325 --- /dev/null +++ b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/xml/FileListToFileMetadataListHandlerTest.java @@ -0,0 +1,81 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.xml; + +import static org.testng.Assert.assertEquals; + +import java.io.InputStream; +import java.net.URI; +import java.util.List; + +import javax.ws.rs.core.MediaType; + +import org.jclouds.http.functions.BaseHandlerTest; +import org.jclouds.mezeo.pcs2.domain.FileMetadata; +import org.jclouds.util.DateService; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; + +/** + * Tests behavior of {@code FileListToFileMetadataListHandler} + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "pcs2.FileListToFileMetadataListHandlerTest") +public class FileListToFileMetadataListHandlerTest extends BaseHandlerTest { + + private DateService dateService; + + @BeforeTest + @Override + protected void setUpInjector() { + super.setUpInjector(); + dateService = injector.getInstance(DateService.class); + assert dateService != null; + } + + @SuppressWarnings("unchecked") + public void testApplyInputStream() { + InputStream is = getClass().getResourceAsStream("/test_file_list.xml"); + List list = ImmutableList.of(new FileMetadata("more", URI + .create("https://pcsbeta.mezeo.net/v2/files/5C81DADC-AAEE-11DE-9D55-B39340AEFF3A"), + dateService.fromSeconds(1254005157), dateService.fromSeconds(1254005158), + dateService.fromSeconds(1254005159), "adrian@jclouds.org", false, false, 1, 254288, + MediaType.APPLICATION_OCTET_STREAM, true), + + new FileMetadata("testfile.txt", URI + .create("https://pcsbeta.mezeo.net/v2/files/9E4C5AFA-A98B-11DE-8B4C-C3884B4A2DA3"), + dateService.fromSeconds(1254000180), dateService.fromSeconds(1254000181), + dateService.fromSeconds(1254000182), "adrian@jclouds.org", false, true, 3, 5, + MediaType.TEXT_PLAIN, false)); + + List result = (List) factory.create( + injector.getInstance(FileListToFileMetadataListHandler.class)).parse(is); + + assertEquals(result, list); + } + +} diff --git a/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/xml/FileMetadataHandlerTest.java b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/xml/FileMetadataHandlerTest.java new file mode 100644 index 0000000000..2176d94213 --- /dev/null +++ b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/xml/FileMetadataHandlerTest.java @@ -0,0 +1,106 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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.mezeo.pcs2.xml; + +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.easymock.classextension.EasyMock.createMock; +import static org.testng.Assert.assertEquals; + +import java.io.InputStream; +import java.net.URI; + +import javax.inject.Singleton; +import javax.ws.rs.core.MediaType; + +import org.jclouds.http.functions.BaseHandlerTest; +import org.jclouds.mezeo.pcs2.PCSUtil; +import org.jclouds.mezeo.pcs2.domain.FileMetadata; +import org.jclouds.util.DateService; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import com.google.inject.AbstractModule; +import com.google.inject.Provides; + +/** + * Tests behavior of {@code FileListToFileMetadataListHandler} + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "pcs2.FileMetadataHandlerTest") +public class FileMetadataHandlerTest extends BaseHandlerTest { + + private DateService dateService; + private PCSUtil util; + + @BeforeTest + @Override + protected void setUpInjector() { + super.setUpInjector(); + injector = injector.createChildInjector(new AbstractModule() { + + @Override + protected void configure() { + } + + @SuppressWarnings("unused") + @Singleton + @Provides + PCSUtil provideUtil() { + util = createMock(PCSUtil.class); + // Note that we should convert uppercase to lowercase! + expect( + util + .get(URI + .create("https://pcsbeta.mezeo.net/v2/files/9E4C5AFA-A98B-11DE-8B4C-C3884B4A2DA3/metadata/Foo"))) + .andReturn("bar"); + replay(util); + return util; + } + + }); + dateService = injector.getInstance(DateService.class); + assert dateService != null; + } + + public void testFileMetadata() { + InputStream is = getClass().getResourceAsStream("/test_file_metadata.xml"); + + FileMetadata expects = new FileMetadata("testfile.txt", URI + .create("https://pcsbeta.mezeo.net/v2/files/9E4C5AFA-A98B-11DE-8B4C-C3884B4A2DA3"), + dateService.fromSeconds(1254000180), dateService.fromSeconds(1254000181), + dateService.fromSeconds(1254000182), "adrian@jclouds.org", false, true, 3, 5, + MediaType.TEXT_PLAIN, false); + // Note that we should convert uppercase to lowercase, since most clouds do anyway + expects.getUserMetadata().put("foo", "bar"); + + FileMetadata result = (FileMetadata) factory.create( + injector.getInstance(FileMetadataHandler.class)).parse(is); + verify(util); + + assertEquals(result, expects); + } +} diff --git a/mezeo/pcs2/core/src/test/resources/test_file_list.xml b/mezeo/pcs2/core/src/test/resources/test_file_list.xml new file mode 100644 index 0000000000..ca3cbc0698 --- /dev/null +++ b/mezeo/pcs2/core/src/test/resources/test_file_list.xml @@ -0,0 +1,95 @@ + + + + test1 + 1254008225 + false + 1254008226 + adrian@jclouds.org + 1 + true + 1254008227 + 1024 + + + + + + + more + 1254005157 + false + 1254005158 + adrian@jclouds.org + 1 + false + 1254005159 + true + application/octet-stream + 254288 + + + + + + + + + testfile.txt + 1254000180 + true + 1254000181 + adrian@jclouds.org + 3 + false + 1254000182 + false + text/plain + 5 + + + + + + + + \ No newline at end of file diff --git a/mezeo/pcs2/core/src/test/resources/test_file_metadata.xml b/mezeo/pcs2/core/src/test/resources/test_file_metadata.xml new file mode 100644 index 0000000000..b8e71462f5 --- /dev/null +++ b/mezeo/pcs2/core/src/test/resources/test_file_metadata.xml @@ -0,0 +1,22 @@ + + + testfile.txt + 1254000180 + true + 1254000181 + adrian@jclouds.org + 3 + False + 1254000182 + false + text/plain + 5 + + + + + + + + + \ No newline at end of file diff --git a/mezeo/pcs2/pom.xml b/mezeo/pcs2/pom.xml index 8c3456f9d0..030a2ff11c 100644 --- a/mezeo/pcs2/pom.xml +++ b/mezeo/pcs2/pom.xml @@ -43,6 +43,7 @@ org.jclouds.mezeo.pcs2.integration.PCSTestInitializer ${jclouds.mezeo.pcs2.user} ${jclouds.mezeo.pcs2.password} + ${jclouds.mezeo.pcs2.endpoint}