View Javadoc
1   package org.argeo.cms.ui.util;
2   
3   import static javax.jcr.Node.JCR_CONTENT;
4   import static javax.jcr.Property.JCR_DATA;
5   import static javax.jcr.nodetype.NodeType.NT_FILE;
6   import static javax.jcr.nodetype.NodeType.NT_RESOURCE;
7   import static org.argeo.cms.ui.CmsConstants.NO_IMAGE_SIZE;
8   
9   import java.io.ByteArrayInputStream;
10  import java.io.IOException;
11  import java.io.InputStream;
12  import java.nio.file.Files;
13  import java.nio.file.Paths;
14  
15  import javax.jcr.Binary;
16  import javax.jcr.Node;
17  import javax.jcr.Property;
18  import javax.jcr.RepositoryException;
19  
20  import org.apache.commons.io.IOUtils;
21  import org.apache.commons.logging.Log;
22  import org.apache.commons.logging.LogFactory;
23  import org.argeo.cms.CmsException;
24  import org.argeo.cms.ui.CmsImageManager;
25  import org.argeo.jcr.JcrUtils;
26  import org.eclipse.rap.rwt.RWT;
27  import org.eclipse.rap.rwt.service.ResourceManager;
28  import org.eclipse.rap.rwt.widgets.FileUpload;
29  import org.eclipse.swt.graphics.Image;
30  import org.eclipse.swt.graphics.ImageData;
31  import org.eclipse.swt.graphics.Point;
32  import org.eclipse.swt.widgets.Control;
33  import org.eclipse.swt.widgets.Display;
34  import org.eclipse.swt.widgets.Label;
35  
36  /** Manages only public images so far. */
37  public class DefaultImageManager implements CmsImageManager {
38  	private final static Log log = LogFactory.getLog(DefaultImageManager.class);
39  //	private MimetypesFileTypeMap fileTypeMap = new MimetypesFileTypeMap();
40  
41  	public Boolean load(Node node, Control control, Point preferredSize) throws RepositoryException {
42  		Point imageSize = getImageSize(node);
43  		Point size;
44  		String imgTag = null;
45  		if (preferredSize == null || imageSize.x == 0 || imageSize.y == 0
46  				|| (preferredSize.x == 0 && preferredSize.y == 0)) {
47  			if (imageSize.x != 0 && imageSize.y != 0) {
48  				// actual image size if completely known
49  				size = imageSize;
50  			} else {
51  				// no image if not completely known
52  				size = resizeTo(NO_IMAGE_SIZE, preferredSize != null ? preferredSize : imageSize);
53  				imgTag = CmsUiUtils.noImg(size);
54  			}
55  
56  		} else if (preferredSize.x != 0 && preferredSize.y != 0) {
57  			// given size if completely provided
58  			size = preferredSize;
59  		} else {
60  			// at this stage :
61  			// image is completely known
62  			assert imageSize.x != 0 && imageSize.y != 0;
63  			// one and only one of the dimension as been specified
64  			assert preferredSize.x == 0 || preferredSize.y == 0;
65  			size = resizeTo(imageSize, preferredSize);
66  		}
67  
68  		boolean loaded = false;
69  		if (control == null)
70  			return loaded;
71  
72  		if (control instanceof Label) {
73  			if (imgTag == null) {
74  				// IMAGE RETRIEVED HERE
75  				imgTag = getImageTag(node, size);
76  				//
77  				if (imgTag == null)
78  					imgTag = CmsUiUtils.noImg(size);
79  				else
80  					loaded = true;
81  			}
82  
83  			Label lbl = (Label) control;
84  			lbl.setText(imgTag);
85  			// lbl.setSize(size);
86  		} else if (control instanceof FileUpload) {
87  			FileUpload lbl = (FileUpload) control;
88  			lbl.setImage(CmsUiUtils.noImage(size));
89  			lbl.setSize(size);
90  			return loaded;
91  		} else
92  			loaded = false;
93  
94  		return loaded;
95  	}
96  
97  	private Point resizeTo(Point orig, Point constraints) {
98  		if (constraints.x != 0 && constraints.y != 0) {
99  			return constraints;
100 		} else if (constraints.x == 0 && constraints.y == 0) {
101 			return orig;
102 		} else if (constraints.y == 0) {// force width
103 			return new Point(constraints.x, scale(orig.y, orig.x, constraints.x));
104 		} else if (constraints.x == 0) {// force height
105 			return new Point(scale(orig.x, orig.y, constraints.y), constraints.y);
106 		}
107 		throw new CmsException("Cannot resize " + orig + " to " + constraints);
108 	}
109 
110 	private int scale(int origDimension, int otherDimension, int otherConstraint) {
111 		return Math.round(origDimension * divide(otherConstraint, otherDimension));
112 	}
113 
114 	private float divide(int a, int b) {
115 		return ((float) a) / ((float) b);
116 	}
117 
118 	public Point getImageSize(Node node) throws RepositoryException {
119 		// TODO optimise
120 		Image image = getSwtImage(node);
121 		return new Point(image.getBounds().width,image.getBounds().height);
122 	}
123 
124 	/** @return null if not available */
125 	@Override
126 	public String getImageTag(Node node) throws RepositoryException {
127 		return getImageTag(node, getImageSize(node));
128 	}
129 
130 	private String getImageTag(Node node, Point size) throws RepositoryException {
131 		StringBuilder buf = getImageTagBuilder(node, size);
132 		if (buf == null)
133 			return null;
134 		return buf.append("/>").toString();
135 	}
136 
137 	/** @return null if not available */
138 	@Override
139 	public StringBuilder getImageTagBuilder(Node node, Point size) throws RepositoryException {
140 		return getImageTagBuilder(node, Integer.toString(size.x), Integer.toString(size.y));
141 	}
142 
143 	/** @return null if not available */
144 	private StringBuilder getImageTagBuilder(Node node, String width, String height) throws RepositoryException {
145 		String url = getImageUrl(node);
146 		if (url == null)
147 			return null;
148 		return CmsUiUtils.imgBuilder(url, width, height);
149 	}
150 
151 	/** @return null if not available */
152 	@Override
153 	public String getImageUrl(Node node) throws RepositoryException {
154 		return CmsUiUtils.getDataPath(node);
155 		// String name = getResourceName(node);
156 		// ResourceManager resourceManager = RWT.getResourceManager();
157 		// if (!resourceManager.isRegistered(name)) {
158 		// InputStream inputStream = null;
159 		// Binary binary = getImageBinary(node);
160 		// if (binary == null)
161 		// return null;
162 		// try {
163 		// inputStream = binary.getStream();
164 		// resourceManager.register(name, inputStream);
165 		// } finally {
166 		// IOUtils.closeQuietly(inputStream);
167 		// JcrUtils.closeQuietly(binary);
168 		// }
169 		// if (log.isTraceEnabled())
170 		// log.trace("Registered image " + name);
171 		// }
172 		// return resourceManager.getLocation(name);
173 	}
174 
175 	protected String getResourceName(Node node) throws RepositoryException {
176 		String workspace = node.getSession().getWorkspace().getName();
177 		if (node.hasNode(JCR_CONTENT))
178 			return workspace + '_' + node.getNode(JCR_CONTENT).getIdentifier();
179 		else
180 			return workspace + '_' + node.getIdentifier();
181 	}
182 
183 	public Binary getImageBinary(Node node) throws RepositoryException {
184 		if (node.isNodeType(NT_FILE)) {
185 			return node.getNode(JCR_CONTENT).getProperty(JCR_DATA).getBinary();
186 		} else {
187 			return null;
188 		}
189 	}
190 
191 	public Image getSwtImage(Node node) throws RepositoryException {
192 		InputStream inputStream = null;
193 		Binary binary = getImageBinary(node);
194 		if (binary == null)
195 			return null;
196 		try {
197 			inputStream = binary.getStream();
198 			return new Image(Display.getCurrent(), inputStream);
199 		} finally {
200 			IOUtils.closeQuietly(inputStream);
201 			JcrUtils.closeQuietly(binary);
202 		}
203 	}
204 
205 	@Override
206 	public String uploadImage(Node parentNode, String fileName, InputStream in) throws RepositoryException {
207 		InputStream inputStream = null;
208 		try {
209 			String previousResourceName = null;
210 			if (parentNode.hasNode(fileName)) {
211 				Node node = parentNode.getNode(fileName);
212 				previousResourceName = getResourceName(node);
213 				if (node.hasNode(JCR_CONTENT)) {
214 					node.getNode(JCR_CONTENT).remove();
215 					node.addNode(JCR_CONTENT, NT_RESOURCE);
216 				}
217 			}
218 
219 			byte[] arr = IOUtils.toByteArray(in);
220 			Node fileNode = JcrUtils.copyBytesAsFile(parentNode, fileName, arr);
221 			inputStream = new ByteArrayInputStream(arr);
222 			ImageData id = new ImageData(inputStream);
223 			processNewImageFile(fileNode, id);
224 
225 			String mime = Files.probeContentType(Paths.get(fileName));
226 			fileNode.setProperty(Property.JCR_MIMETYPE, mime);
227 			fileNode.getSession().save();
228 
229 			// reset resource manager
230 			ResourceManager resourceManager = RWT.getResourceManager();
231 			if (previousResourceName != null && resourceManager.isRegistered(previousResourceName)) {
232 				resourceManager.unregister(previousResourceName);
233 				if (log.isDebugEnabled())
234 					log.debug("Unregistered image " + previousResourceName);
235 			}
236 			return getImageUrl(fileNode);
237 		} catch (IOException e) {
238 			throw new CmsException("Cannot upload image " + fileName + " in " + parentNode, e);
239 		} finally {
240 			IOUtils.closeQuietly(inputStream);
241 		}
242 	}
243 
244 	/** Does nothign by default. */
245 	protected void processNewImageFile(Node fileNode, ImageData id) throws RepositoryException, IOException {
246 	}
247 }