Merging DEV_TEMPORARY to HEAD (RenditionService)

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@19103 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Neil McErlean
2010-03-05 20:02:52 +00:00
parent ad84497735
commit bce28a5599
80 changed files with 10611 additions and 1815 deletions

View File

@@ -16,6 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.content.metadata.xml;
import java.io.Serializable;
@@ -26,37 +27,38 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.repo.content.selector.ContentWorkerSelector;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.content.metadata.AbstractMappingMetadataExtracter;
import org.alfresco.repo.content.metadata.MetadataExtracter;
import org.alfresco.repo.content.selector.ContentWorkerSelector;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.namespace.QName;
import org.springframework.extensions.surf.util.PropertyCheck;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.surf.util.PropertyCheck;
/**
* A metadata extractor that selects an appropiate workder for the extraction.
* <p>
* The {@linkplain #setSelectors(List) selectors} are used to find an extracter most
* appropriate of a given XML document. The chosen extracter is then asked to extract
* the values, passing through the {@linkplain MetadataExtracter.OverwritePolicy overwrite policy}
* as {@linkplain #setOverwritePolicy(String)} on this instance. The overwrite policy of the
* embedded extracters is not relevant unless they are used separately in another context.
* The {@linkplain #setSelectors(List) selectors} are used to find an extracter
* most appropriate of a given XML document. The chosen extracter is then asked
* to extract the values, passing through the
* {@linkplain MetadataExtracter.OverwritePolicy overwrite policy} as
* {@linkplain #setOverwritePolicy(String)} on this instance. The overwrite
* policy of the embedded extracters is not relevant unless they are used
* separately in another context.
*
* @see ContentWorkerSelector
* @see MetadataExtracter
*
* @since 2.1
* @author Derek Hulley
*/
public class XmlMetadataExtracter extends AbstractMappingMetadataExtracter
{
public static String[] SUPPORTED_MIMETYPES = new String[] {MimetypeMap.MIMETYPE_XML};
public static String[] SUPPORTED_MIMETYPES = new String[] { MimetypeMap.MIMETYPE_XML };
private static Log logger = LogFactory.getLog(XPathMetadataExtracter.class);
private List<ContentWorkerSelector<MetadataExtracter>> selectors;
/**
@@ -68,11 +70,11 @@ public class XmlMetadataExtracter extends AbstractMappingMetadataExtracter
}
/**
* Sets the list of metadata selectors to use to find the extracter to use, given
* some content. The evaluations are done in the order that they occur in the
* list.
* Sets the list of metadata selectors to use to find the extracter to use,
* given some content. The evaluations are done in the order that they occur
* in the list.
*
* @param selectors A list of selectors
* @param selectors A list of selectors
*/
public void setSelectors(List<ContentWorkerSelector<MetadataExtracter>> selectors)
{
@@ -88,9 +90,10 @@ public class XmlMetadataExtracter extends AbstractMappingMetadataExtracter
}
/**
* It is not possible to have any default mappings, but something has to be returned.
* It is not possible to have any default mappings, but something has to be
* returned.
*
* @return Returns an empty map
* @return Returns an empty map
*/
@Override
protected Map<String, Set<QName>> getDefaultMapping()
@@ -102,25 +105,22 @@ public class XmlMetadataExtracter extends AbstractMappingMetadataExtracter
* Selects and extracter to perform the work and redirects to it.
*/
@Override
public Map<QName, Serializable> extract(
ContentReader reader,
OverwritePolicy overwritePolicy,
Map<QName, Serializable> destination,
Map<String, Set<QName>> mapping)
public Map<QName, Serializable> extract(ContentReader reader, OverwritePolicy overwritePolicy,
Map<QName, Serializable> destination, Map<String, Set<QName>> mapping)
{
// Check the content length
if (reader.getSize() == 0)
{
// There is no content. We don't spoof any properties so there can be nothing extracted.
// There is no content. We don't spoof any properties so there can
// be nothing extracted.
if (logger.isDebugEnabled())
{
logger.debug("\n" +
"XML document has zero length, so bypassing extraction: \n" +
" Document: " + reader);
logger.debug("\n" + "XML document has zero length, so bypassing extraction: \n" + " Document: "
+ reader);
}
return destination;
}
MetadataExtracter extracter = null;
// Select a worker
for (ContentWorkerSelector<MetadataExtracter> selector : selectors)
@@ -138,9 +138,8 @@ public class XmlMetadataExtracter extends AbstractMappingMetadataExtracter
{
if (reader.isChannelOpen())
{
logger.error("Content reader not closed by MetadataExtractor selector: \n" +
" reader: " + reader + "\n" +
" selector: " + selector);
logger.error("Content reader not closed by MetadataExtractor selector: \n" + " reader: "
+ reader + "\n" + " selector: " + selector);
}
}
// Just take the first successful one
@@ -148,10 +147,8 @@ public class XmlMetadataExtracter extends AbstractMappingMetadataExtracter
{
if (logger.isDebugEnabled())
{
logger.debug("\n" +
"Found metadata extracter to process XML document: \n" +
" Selector: " + selector + "\n" +
" Document: " + reader);
logger.debug("\n" + "Found metadata extracter to process XML document: \n" + " Selector: "
+ selector + "\n" + " Document: " + reader);
}
break;
}
@@ -162,9 +159,7 @@ public class XmlMetadataExtracter extends AbstractMappingMetadataExtracter
{
if (logger.isDebugEnabled())
{
logger.debug("\n" +
"No working metadata extractor could be found: \n" +
" Document: " + reader);
logger.debug("\n" + "No working metadata extractor could be found: \n" + " Document: " + reader);
}
// There will be no properties extracted
modifiedProperties = destination;
@@ -180,26 +175,22 @@ public class XmlMetadataExtracter extends AbstractMappingMetadataExtracter
{
if (reader.isChannelOpen())
{
logger.error("Content reader not closed by MetadataExtractor: \n" +
" Reader: " + reader + "\n" +
" extracter: " + extracter);
logger.error("Content reader not closed by MetadataExtractor: \n" + " Reader: " + reader + "\n"
+ " extracter: " + extracter);
}
}
}
// Done
if (logger.isDebugEnabled())
{
logger.debug("\n" +
"XML metadata extractor redirected: \n" +
" Reader: " + reader + "\n" +
" Extracter: " + extracter + "\n" +
" Metadata: " + modifiedProperties);
logger.debug("\n" + "XML metadata extractor redirected: \n" + " Reader: " + reader + "\n"
+ " Extracter: " + extracter + "\n" + " Metadata: " + modifiedProperties);
}
return modifiedProperties;
}
/**
* This is not required as the
* This is not required as the
*/
protected Map<String, Serializable> extractRaw(ContentReader reader) throws Throwable
{

View File

@@ -0,0 +1,175 @@
/*
* Copyright (C) 2005-2010 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.content.transform.magick;
/**
* DTO used to store options for ImageMagick cropping.
*
* @author Nick Smith
*/
public class ImageCropOptions
{
private int height = -1;
private int width = -1;
private int xOffset = 0;
private int yOffset = 0;
private boolean isPercentageCrop = false;
private String gravity = null;
/**
* Gets the height of the cropped image. By default this is in pixels but if
* <code>isPercentageCrop</code> is set to true then it changes to
* percentage.
*
* @return the height
*/
public int getHeight()
{
return this.height;
}
/**
* Sets the height of the cropped image. By default this is in pixels but if
* <code>isPercentageCrop</code> is set to true then it changes to
* percentage.
*
* @param height the height to set
*/
public void setHeight(int height)
{
this.height = height;
}
/**
* Sets the width of the cropped image. By default this is in pixels but if
* <code>isPercentageCrop</code> is set to true then it changes to
* percentage.
*
* @return the width
*/
public int getWidth()
{
return this.width;
}
/**
* Sets the width of the cropped image. By default this is in pixels but if
* <code>isPercentageCrop</code> is set to true then it changes to
* percentage.
*
* @param width the width to set
*/
public void setWidth(int width)
{
this.width = width;
}
/**
* Gets the horizontal offset. By default this starts fromt he top-left
* corner of the image and moves right, however the <code>gravity</code>
* property can change this.
*
* @return the xOffset
*/
public int getXOffset()
{
return this.xOffset;
}
/**
* Sets the horizontal offset. By default this starts fromt he top-left
* corner of the image and moves right, however the <code>gravity</code>
* property can change this.
*
* @param xOffset the xOffset to set
*/
public void setXOffset(int xOffset)
{
this.xOffset = xOffset;
}
/**
* Gets the vertical offset. By default this starts fromt he top-left corner
* of the image and moves down, however the <code>gravity</code> property
* can change this.
*
* @return the yOffset
*/
public int getYOffset()
{
return this.yOffset;
}
/**
* Sets the vertical offset. By default this starts fromt he top-left corner
* of the image and moves down, however the <code>gravity</code> property
* can change this.
*
* @param yOffset the yOffset to set
*/
public void setYOffset(int yOffset)
{
this.yOffset = yOffset;
}
/**
* @return the isPercentageCrop
*/
public boolean isPercentageCrop()
{
return this.isPercentageCrop;
}
/**
* @param isPercentageCrop the isPercentageCrop to set
*/
public void setPercentageCrop(boolean isPercentageCrop)
{
this.isPercentageCrop = isPercentageCrop;
}
/**
* Sets the 'gravity' which determines how the offset is applied. It affects
* both the origin of offset and the direction(s).
*
* @param gravity the gravity to set
*/
public void setGravity(String gravity)
{
this.gravity = gravity;
}
/**
* Gets the 'gravity' which determines how the offset is applied. It affects
* both the origin of offset and the direction(s).
*
* @return the gravity
*/
public String getGravity()
{
return this.gravity;
}
}

View File

@@ -149,8 +149,13 @@ public class ImageMagickContentTransformerWorker extends AbstractImageMagickCont
if (options instanceof ImageTransformationOptions)
{
ImageTransformationOptions imageOptions = (ImageTransformationOptions)options;
ImageCropOptions cropOptions = imageOptions.getCropOptions();
ImageResizeOptions resizeOptions = imageOptions.getResizeOptions();
String commandOptions = imageOptions.getCommandOptions();
if (cropOptions != null)
{
commandOptions = commandOptions + " " + getImageCropCommandOptions(cropOptions);
}
if (resizeOptions != null)
{
commandOptions = commandOptions + " " + getImageResizeCommandOptions(resizeOptions);
@@ -173,6 +178,59 @@ public class ImageMagickContentTransformerWorker extends AbstractImageMagickCont
}
}
/**
* Gets the imagemagick command string for the image crop options provided
*
* @param imageResizeOptions image resize options
* @return String the imagemagick command options
*/
private String getImageCropCommandOptions(ImageCropOptions cropOptions)
{
StringBuilder builder = new StringBuilder(32);
String gravity = cropOptions.getGravity();
if(gravity!=null)
{
builder.append("-gravity ");
builder.append(gravity);
builder.append(" ");
}
builder.append("-crop ");
int width = cropOptions.getWidth();
if (width > -1)
{
builder.append(width);
}
int height = cropOptions.getHeight();
if (height > -1)
{
builder.append("x");
builder.append(height);
}
if (cropOptions.isPercentageCrop())
{
builder.append("%");
}
appendOffset(builder, cropOptions.getXOffset());
appendOffset(builder, cropOptions.getYOffset());
builder.append(" +repage");
return builder.toString();
}
/**
* @param builder
* @param xOffset
*/
private void appendOffset(StringBuilder builder, int xOffset)
{
if(xOffset>=0)
{
builder.append("+");
}
builder.append(xOffset);
}
/**
* Gets the imagemagick command string for the image resize options provided
*

View File

@@ -33,6 +33,9 @@ public class ImageTransformationOptions extends TransformationOptions
/** Image resize options */
private ImageResizeOptions resizeOptions;
/** Image crop options */
private ImageCropOptions cropOptions;
/**
* Set the command string options
*
@@ -84,4 +87,20 @@ public class ImageTransformationOptions extends TransformationOptions
return msg.toString();
}
/**
* @param cropOptions the cropOptions to set
*/
public void setCropOptions(ImageCropOptions cropOptions)
{
this.cropOptions = cropOptions;
}
/**
* @return the cropOptions
*/
public ImageCropOptions getCropOptions()
{
return this.cropOptions;
}
}