/*
* Copyright 2000-2013 Enonic AS
* http://www.enonic.com/license
*/
package com.enonic.cms.itest.portal;
import java.io.IOException;
import java.util.Date;
import javax.servlet.http.HttpServletResponse;
import org.joda.time.DateTime;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.orm.hibernate3.HibernateTemplate;
import com.google.common.collect.Sets;
import com.google.common.io.ByteStreams;
import com.enonic.cms.api.client.model.CreateImageContentParams;
import com.enonic.cms.api.client.model.content.image.ImageBinaryInput;
import com.enonic.cms.api.client.model.content.image.ImageContentDataInput;
import com.enonic.cms.api.client.model.content.image.ImageNameInput;
import com.enonic.cms.core.client.InternalClientContentService;
import com.enonic.cms.core.content.ContentAndVersion;
import com.enonic.cms.core.content.ContentEntity;
import com.enonic.cms.core.content.ContentKey;
import com.enonic.cms.core.content.ContentStatus;
import com.enonic.cms.core.content.ContentVersionEntity;
import com.enonic.cms.core.content.binary.BinaryDataEntity;
import com.enonic.cms.core.content.binary.ContentBinaryDataEntity;
import com.enonic.cms.core.content.contentdata.ContentData;
import com.enonic.cms.core.content.contenttype.ContentHandlerName;
import com.enonic.cms.core.preview.ContentPreviewContext;
import com.enonic.cms.core.preview.PreviewContext;
import com.enonic.cms.core.preview.PreviewService;
import com.enonic.cms.core.security.PortalSecurityHolder;
import com.enonic.cms.core.security.user.UserEntity;
import com.enonic.cms.core.security.user.UserKey;
import com.enonic.cms.core.security.user.UserType;
import com.enonic.cms.core.servlet.ServletRequestAccessor;
import com.enonic.cms.core.structure.SiteEntity;
import com.enonic.cms.core.structure.SitePath;
import com.enonic.cms.core.structure.SitePropertiesServiceImpl;
import com.enonic.cms.core.structure.menuitem.MenuItemEntity;
import com.enonic.cms.core.time.MockTimeService;
import com.enonic.cms.itest.AbstractSpringTest;
import com.enonic.cms.itest.util.DomainFactory;
import com.enonic.cms.itest.util.DomainFixture;
import com.enonic.cms.web.portal.PortalWebContext;
import com.enonic.cms.web.portal.image.ImageHandler;
import com.enonic.cms.web.portal.image.ImageRequestException;
import static org.junit.Assert.*;
public class ImageControllerTest
extends AbstractSpringTest
{
@Autowired
protected HibernateTemplate hibernateTemplate;
protected DomainFactory factory;
@Autowired
protected DomainFixture fixture;
@Autowired
private InternalClientContentService internalClientContentService;
private PreviewService previewService;
@Autowired
private ImageHandler imageHandler;
@Autowired
private SitePropertiesServiceImpl sitePropertiesService;
private MockHttpServletRequest httpServletRequest = new MockHttpServletRequest();
private MockHttpServletResponse httpServletResponse = new MockHttpServletResponse();
private SiteEntity site1;
private PortalWebContext webContext;
@Before
public void before()
{
factory = fixture.getFactory();
fixture.initSystemData();
fixture.createAndStoreUserAndUserGroup( "testuser", "testuser fullname", UserType.NORMAL, "testuserstore" );
httpServletRequest.setCharacterEncoding( "UTF-8" );
ServletRequestAccessor.setRequest( httpServletRequest );
loginUserInPortal( fixture.findUserByName( "testuser" ).getKey() );
previewService = Mockito.mock( PreviewService.class );
Mockito.when( previewService.isInPreview() ).thenReturn( false );
Mockito.when( previewService.getPreviewContext() ).thenReturn( PreviewContext.NO_PREVIEW );
imageHandler.setPreviewService( previewService );
MockTimeService timeService = new MockTimeService( new DateTime( 2011, 6, 27, 12, 0, 0, 0 ) );
imageHandler.setTimeService( timeService );
site1 = factory.createSite( "MySite", new Date(), null, "en" );
fixture.save( site1 );
MenuItemEntity firstPage = createPage( "Firstpage", null, "MySite" );
fixture.save( firstPage );
site1.setFirstPage( firstPage );
fixture.flushAndClearHibernateSession();
fixture.save( factory.createContentHandler( "Image content", ContentHandlerName.IMAGE.getHandlerClassShortName() ) );
fixture.save( factory.createContentType( "ImageContentType", ContentHandlerName.IMAGE.getHandlerClassShortName() ) );
fixture.save( factory.createUnit( "ImageUnit" ) );
fixture.save( factory.createCategory( "ImageCategory", null, "ImageContentType", "ImageUnit", "testuser", "testuser" ) );
fixture.save( factory.createCategoryAccessForUser( "ImageCategory", "testuser", "read, create, approve" ) );
fixture.flushAndClearHibernateSession();
webContext = new PortalWebContext();
webContext.setRequest( this.httpServletRequest );
webContext.setResponse( this.httpServletResponse );
sitePropertiesService.restart();
}
@Test
public void request_content_image_without_format_gives_png_as_content_type()
throws Exception
{
byte[] bytes = loadImage( "Arn.JPG" );
ContentKey contentKey =
createImageContent( "MyImage.jpg", 2, bytes, "ImageCategory", new DateTime( 2011, 6, 27, 10, 0, 0, 0 ), null );
String imageRequestPath = "_image/" + contentKey.toString();
setPathInfoAndRequestURI( httpServletRequest, imageRequestPath );
httpServletRequest.setParameter( "_background", "0xffffff" );
httpServletRequest.setParameter( "_quality", "100" );
imageHandler.handle( webContext );
assertEquals( "image/png", httpServletResponse.getContentType() );
assertEquals( HttpServletResponse.SC_OK, httpServletResponse.getStatus() );
}
@Test
public void request_content_image_with_format_gives_same_content_type()
throws Exception
{
byte[] bytes = loadImage( "Arn.JPG" );
ContentKey contentKey =
createImageContent( "MyImage.jpg", 2, bytes, "ImageCategory", new DateTime( 2011, 6, 27, 10, 0, 0, 0 ), null );
String imageRequestPath = "_image/" + contentKey.toString() + ".jpg";
setPathInfoAndRequestURI( httpServletRequest, imageRequestPath );
httpServletRequest.setParameter( "_background", "0xffffff" );
httpServletRequest.setParameter( "_quality", "100" );
imageHandler.handle( webContext );
assertEquals( "image/jpg", httpServletResponse.getContentType() );
assertEquals( HttpServletResponse.SC_OK, httpServletResponse.getStatus() );
}
@Test
public void request_content_image_with_label_small()
throws Exception
{
byte[] bytes = loadImage( "Arn.JPG" );
ContentKey contentKey =
createImageContent( "MyImage.jpg", 2, bytes, "ImageCategory", new DateTime( 2011, 6, 27, 10, 0, 0, 0 ), null );
String imageRequestPath = "_image/" + contentKey.toString() + "/label/small";
setPathInfoAndRequestURI( httpServletRequest, imageRequestPath );
httpServletRequest.setParameter( "_background", "0xffffff" );
httpServletRequest.setParameter( "_quality", "100" );
imageHandler.handle( webContext );
assertEquals( "image/png", httpServletResponse.getContentType() );
assertEquals( HttpServletResponse.SC_OK, httpServletResponse.getStatus() );
}
@Test
public void request_content_image_that_does_not_exist()
throws Exception
{
String imageRequestPath = "_image/123" + ".jpg";
setPathInfoAndRequestURI( httpServletRequest, imageRequestPath );
httpServletRequest.setParameter( "_background", "0xffffff" );
httpServletRequest.setParameter( "_quality", "100" );
try
{
imageHandler.handle( webContext );
fail( "Expected exception" );
}
catch ( Exception e )
{
assertTrue( e instanceof ImageRequestException );
ImageRequestException imageRequestException = (ImageRequestException) e;
assertTrue( imageRequestException.getMessage().contains( "Resource '/_image/123.jpg' not found" ) );
}
}
@Test
public void request_content_image_with_label_that_does_not_exist()
throws Exception
{
byte[] bytes = loadImage( "Arn.JPG" );
ContentKey contentKey =
createImageContent( "MyImage.jpg", 2, bytes, "ImageCategory", new DateTime( 2011, 6, 27, 10, 0, 0, 0 ), null );
String imageRequestPath = "_image/" + contentKey + "/label/nonexistinglabel.jpg";
setPathInfoAndRequestURI( httpServletRequest, imageRequestPath );
httpServletRequest.setParameter( "_background", "0xffffff" );
httpServletRequest.setParameter( "_quality", "100" );
try
{
imageHandler.handle( webContext );
fail( "Expected exception" );
}
catch ( Exception e )
{
assertTrue( e instanceof ImageRequestException );
ImageRequestException imageRequestException = (ImageRequestException) e;
assertTrue( imageRequestException.getMessage().contains(
"Resource '/_image/" + contentKey + "/label/nonexistinglabel.jpg' not found" ) );
}
}
@Test
public void request_content_image_that_is_deleted()
throws Exception
{
byte[] bytes = loadImage( "Arn.JPG" );
ContentKey contentKey =
createImageContent( "MyImage.jpg", 2, bytes, "ImageCategory", new DateTime( 2011, 6, 27, 10, 0, 0, 0 ), null );
ContentEntity content = fixture.findContentByKey( contentKey );
content.setDeleted( true );
String imageRequestPath = "_image/" + contentKey + ".jpg";
setPathInfoAndRequestURI( httpServletRequest, imageRequestPath );
httpServletRequest.setParameter( "_background", "0xffffff" );
httpServletRequest.setParameter( "_quality", "100" );
try
{
imageHandler.handle( webContext );
fail( "Expected exception" );
}
catch ( Exception e )
{
assertTrue( e instanceof ImageRequestException );
ImageRequestException imageRequestException = (ImageRequestException) e;
assertTrue( imageRequestException.getMessage().contains( "Resource '/_image/" + contentKey + ".jpg' not found" ) );
}
}
@Test
public void request_content_image_that_is_not_online()
throws Exception
{
byte[] bytes = loadImage( "Arn.JPG" );
ContentKey contentKey =
createImageContent( "MyImage.jpg", 2, bytes, "ImageCategory", new DateTime( 2011, 6, 27, 13, 0, 0, 0 ), null );
String imageRequestPath = "_image/" + contentKey + ".jpg";
setPathInfoAndRequestURI( httpServletRequest, imageRequestPath );
httpServletRequest.setParameter( "_background", "0xffffff" );
httpServletRequest.setParameter( "_quality", "100" );
try
{
imageHandler.handle( webContext );
fail( "Expected exception" );
}
catch ( Exception e )
{
assertTrue( e instanceof ImageRequestException );
ImageRequestException imageRequestException = (ImageRequestException) e;
assertTrue( imageRequestException.getMessage().contains( "Resource '/_image/" + contentKey + ".jpg' not found" ) );
}
}
@Test
public void request_content_image_with_no_access()
throws Exception
{
byte[] bytes = loadImage( "Arn.JPG" );
ContentKey contentKey =
createImageContent( "MyImage.jpg", 2, bytes, "ImageCategory", new DateTime( 2011, 6, 27, 10, 0, 0, 0 ), null );
fixture.createAndStoreUserAndUserGroup( "user-with-no-access", "testuser fullname", UserType.NORMAL, "testuserstore" );
loginUserInPortal( fixture.findUserByName( "user-with-no-access" ).getKey() );
String imageRequestPath = "_image/" + contentKey + ".jpg";
setPathInfoAndRequestURI( httpServletRequest, imageRequestPath );
httpServletRequest.setParameter( "_background", "0xffffff" );
httpServletRequest.setParameter( "_quality", "100" );
try
{
imageHandler.handle( webContext );
fail( "Expected exception" );
}
catch ( Exception e )
{
assertTrue( e instanceof ImageRequestException );
ImageRequestException imageRequestException = (ImageRequestException) e;
assertTrue( imageRequestException.getMessage().contains( "Resource '/_image/" + contentKey + ".jpg' not found" ) );
}
}
@Test
public void request_content_image_that_binary_is_on_main_version()
throws Exception
{
// setup: content
byte[] bytes = loadImage( "Arn.JPG" );
ContentKey contentKey =
createImageContent( "MyImage.jpg", 2, bytes, "ImageCategory", new DateTime( 2011, 6, 27, 10, 0, 0, 0 ), null );
// setup: draft version of content
ContentEntity content = fixture.findContentByKey( contentKey );
BinaryDataEntity binaryDataOfMainVersion = content.getMainVersion().getBinaryData( "source" );
// exercise & verify
String imageRequestPath = "_image/" + contentKey + "/binary/" + binaryDataOfMainVersion.getKey() + ".jpg";
setPathInfoAndRequestURI( httpServletRequest, imageRequestPath );
httpServletRequest.setParameter( "_background", "0xffffff" );
httpServletRequest.setParameter( "_quality", "100" );
imageHandler.handle( webContext );
assertEquals( HttpServletResponse.SC_OK, httpServletResponse.getStatus() );
assertTrue( "Content Length", httpServletResponse.getContentLength() > 0 );
assertEquals( "image/jpg", httpServletResponse.getContentType() );
}
@Test
public void exception_thrown_for_request_to_content_image_that_binary_is_not_on_main_version()
throws Exception
{
// setup: content
byte[] bytes = loadImage( "Arn.JPG" );
ContentKey contentKey =
createImageContent( "MyImage.jpg", 2, bytes, "ImageCategory", new DateTime( 2011, 6, 27, 10, 0, 0, 0 ), null );
// setup: draft version of content
ContentEntity content = fixture.findContentByKey( contentKey );
ContentVersionEntity draftVersion = createDraftVersion( "Arn.JPG" );
draftVersion.setContentDataXml( content.getMainVersion().getContentDataAsXmlString() );
content.setDraftVersion( draftVersion );
content.addVersion( draftVersion );
fixture.save( draftVersion );
BinaryDataEntity binaryDataForDraftVersion = factory.createBinaryData( "Arn.JPG", bytes.length );
binaryDataForDraftVersion.setBlobKey( content.getMainVersion().getBinaryData( "source" ).getBlobKey() );
fixture.save( binaryDataForDraftVersion );
ContentBinaryDataEntity contentBinaryDataForDraftVersion =
factory.createContentBinaryData( "source", binaryDataForDraftVersion, draftVersion );
draftVersion.addContentBinaryData( contentBinaryDataForDraftVersion );
fixture.save( contentBinaryDataForDraftVersion );
fixture.flushAndClearHibernateSession();
// exercise & verify
String imageRequestPath = "_image/" + contentKey + "/binary/" + binaryDataForDraftVersion.getKey() + ".jpg";
setPathInfoAndRequestURI( httpServletRequest, imageRequestPath );
httpServletRequest.setParameter( "_version", draftVersion.getKey().toString() );
httpServletRequest.setParameter( "_background", "0xffffff" );
httpServletRequest.setParameter( "_quality", "100" );
try
{
imageHandler.handle( webContext );
fail( "Expected exception" );
}
catch ( Exception e )
{
assertTrue( e instanceof ImageRequestException );
ImageRequestException imageRequestException = (ImageRequestException) e;
assertTrue( imageRequestException.getMessage().contains(
"Resource '/_image/" + contentKey + "/binary/" + binaryDataForDraftVersion.getKey() + ".jpg' not found" ) );
}
}
@Test
public void request_user_image()
throws Exception
{
byte[] bytes = loadImage( "Arn.JPG" );
UserEntity testUser = fixture.findUserByName( "testuser" );
testUser.setPhoto( bytes );
fixture.flushAndClearHibernateSession();
String imageRequestPath = "_image/user/" + testUser.getKey() + ".jpg";
setPathInfoAndRequestURI( httpServletRequest, imageRequestPath );
httpServletRequest.setParameter( "_background", "0xffffff" );
httpServletRequest.setParameter( "_quality", "100" );
imageHandler.handle( webContext );
assertEquals( HttpServletResponse.SC_OK, httpServletResponse.getStatus() );
assertEquals( "image/jpg", httpServletResponse.getContentType() );
}
@Test
public void response_ok_for_request_to_content_image_that_is_not_online_when_is_related_to_content_in_preview()
throws Exception
{
// setup: content
byte[] bytes = loadImage( "Arn.JPG" );
ContentKey contentKey =
createImageContent( "MyImage.jpg", 2, bytes, "ImageCategory", new DateTime( 2011, 6, 27, 13, 0, 0, 0 ), null );
// setup: preview
Mockito.when( previewService.isInPreview() ).thenReturn( true );
ContentEntity contentPreviewed = new ContentEntity();
ContentData contentData = Mockito.mock( ContentData.class );
Mockito.when( contentData.resolveRelatedContentKeys() ).thenReturn( Sets.newHashSet( contentKey ) );
ContentVersionEntity versionPreviewed = Mockito.mock( ContentVersionEntity.class );
Mockito.when( versionPreviewed.getContentData() ).thenReturn( contentData );
versionPreviewed.setContentData( contentData );
ContentAndVersion contentAndVersionPreviewed = new ContentAndVersion( contentPreviewed, versionPreviewed );
ContentPreviewContext contentPreviewContext = new ContentPreviewContext( contentAndVersionPreviewed );
PreviewContext previewContext = new PreviewContext( contentPreviewContext );
Mockito.when( previewService.getPreviewContext() ).thenReturn( previewContext );
// exercise & verify
String imageRequestPath = "_image/" + contentKey;
setPathInfoAndRequestURI( httpServletRequest, imageRequestPath );
httpServletRequest.setParameter( "_background", "0xffffff" );
httpServletRequest.setParameter( "_quality", "100" );
imageHandler.handle( webContext );
assertEquals( HttpServletResponse.SC_OK, httpServletResponse.getStatus() );
assertTrue( "Content Length", httpServletResponse.getContentLength() > 0 );
}
@Test
public void exception_thrown_for_request_to_content_image_that_is_not_online_when_is_not_related_to_content_in_preview()
throws Exception
{
// setup: content
byte[] bytes = loadImage( "Arn.JPG" );
ContentKey contentKey =
createImageContent( "MyImage.jpg", 2, bytes, "ImageCategory", new DateTime( 2011, 6, 27, 13, 0, 0, 0 ), null );
// setup: preview
Mockito.when( previewService.isInPreview() ).thenReturn( true );
ContentEntity contentPreviewed = new ContentEntity();
ContentData contentData = Mockito.mock( ContentData.class );
Mockito.when( contentData.resolveRelatedContentKeys() ).thenReturn( Sets.newHashSet( new ContentKey( 666 ) ) );
ContentVersionEntity versionPreviewed = Mockito.mock( ContentVersionEntity.class );
Mockito.when( versionPreviewed.getContentData() ).thenReturn( contentData );
versionPreviewed.setContentData( contentData );
ContentAndVersion contentAndVersionPreviewed = new ContentAndVersion( contentPreviewed, versionPreviewed );
ContentPreviewContext contentPreviewContext = new ContentPreviewContext( contentAndVersionPreviewed );
PreviewContext previewContext = new PreviewContext( contentPreviewContext );
Mockito.when( previewService.getPreviewContext() ).thenReturn( previewContext );
// exercise & verify
String imageRequestPath = "_image/" + contentKey;
setPathInfoAndRequestURI( httpServletRequest, imageRequestPath );
httpServletRequest.setParameter( "_background", "0xffffff" );
httpServletRequest.setParameter( "_quality", "100" );
try
{
imageHandler.handle( webContext );
fail( "Expected exception" );
}
catch ( Exception e )
{
assertTrue( e instanceof ImageRequestException );
assertTrue( e.getMessage().contains( "Resource '/_image/" + contentKey + "' not found" ) );
}
}
private MenuItemEntity createPage( String name, String parentName, String siteName )
{
return factory.createPageMenuItem( name, 0, name, name, siteName, "testuser", "testuser", false, false, "en", parentName, 0,
new Date(), false, null );
}
private ContentKey createImageContent( String name, int contentStatus, byte[] bytes, String categoryName, DateTime availableFrom,
DateTime availableTo )
throws IOException
{
ImageContentDataInput imageContentDataInput = new ImageContentDataInput();
imageContentDataInput.name = new ImageNameInput( name );
imageContentDataInput.binary = new ImageBinaryInput( bytes, name );
CreateImageContentParams params = new CreateImageContentParams();
params.categoryKey = fixture.findCategoryByName( categoryName ).getKey().toInt();
params.publishFrom = availableFrom != null ? availableFrom.toDate() : null;
params.publishTo = availableTo != null ? availableTo.toDate() : null;
params.status = contentStatus;
params.contentData = imageContentDataInput;
return new ContentKey( internalClientContentService.createImageContent( params ) );
}
private byte[] loadImage( String fileName )
throws IOException
{
ClassPathResource resource = new ClassPathResource( ImageControllerTest.class.getName().replace( ".", "/" ) + "-" + fileName );
return ByteStreams.toByteArray( resource.getInputStream() );
}
private ContentVersionEntity createDraftVersion( String title )
{
ContentVersionEntity draftVersion = factory.createContentVersion( "" + ContentStatus.DRAFT.getKey(), "testuser/testuserstore" );
draftVersion.setCreatedAt( new Date() );
draftVersion.setModifiedAt( new Date() );
draftVersion.setModifiedBy( fixture.findUserByName( "testuser" ) );
draftVersion.setTitle( title );
return draftVersion;
}
private void loginUserInPortal( UserKey userKey )
{
PortalSecurityHolder.setImpersonatedUser( userKey );
PortalSecurityHolder.setLoggedInUser( userKey );
}
private void setPathInfoAndRequestURI( MockHttpServletRequest httpServletRequest, String imageRequestPath )
{
httpServletRequest.setRequestURI( "/site/" + site1.getKey() + "/" + imageRequestPath );
httpServletRequest.setPathInfo( "/" + site1.getKey() + "/" + imageRequestPath );
webContext.setSitePath( new SitePath( site1.getKey(), "/" + imageRequestPath ) );
}
}